diff --git a/.gitignore b/.gitignore
index 91cfcaea..9c9e6a9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,3 +28,9 @@ coverage/
# Claude Code
.claude/
+packages/ibkr/ref/source/JavaClient/
+packages/ibkr/ref/source/cppclient/
+packages/ibkr/ref/samples/Java/
+packages/ibkr/ref/samples/Cpp/
+packages/ibkr/ref/CMakeLists.txt
+packages/ibkr/src/protobuf/
diff --git a/packages/ibkr/DESIGN.md b/packages/ibkr/DESIGN.md
new file mode 100644
index 00000000..0eb5a5ef
--- /dev/null
+++ b/packages/ibkr/DESIGN.md
@@ -0,0 +1,192 @@
+# IBKR TWS API TypeScript Port — Design Notes
+
+This document captures the exploration, decisions, and trade-offs made during the development of `@traderalice/ibkr`. If you're wondering "why is it done this way?", this is where to look.
+
+## Background
+
+Open Alice needed IBKR trading support. The Unified Trading Account system was already designed in IBKR's style, so the data model was a natural fit. The question was how to connect.
+
+## Evaluating Connection Options
+
+### Option 1: `@stoqey/ib` (community npm package)
+
+A community TypeScript implementation of the TWS socket protocol.
+
+- **Pros**: Ready to use, npm install and go.
+- **Cons**: 340 GitHub stars at the time of evaluation. Open Alice itself had 1100+. Depending on a smaller project for a critical path (real-money trading) was deemed too risky. Supply chain concerns: single maintainer, infrequent updates, unclear maintenance commitment.
+
+**Decision**: Rejected due to supply chain risk.
+
+### Option 2: Client Portal REST API
+
+IBKR provides a separate REST gateway (Client Portal) that exposes JSON endpoints on localhost.
+
+- **Pros**: Zero dependencies, just `fetch()`. Simple to implement.
+- **Cons**: Requires running an additional Java process (separate from IB Gateway/TWS). Session timeout requires periodic `/tickle` keepalive. Feature coverage is a subset of the full TWS API. SSL certificate handling is awkward (self-signed certs).
+
+**Decision**: Considered as a pragmatic fallback, but ultimately not chosen because the full TWS API port turned out to be feasible.
+
+### Option 3: Self-built TWS socket protocol
+
+Port the official IBKR client directly to TypeScript. The official distribution includes clients in Java, Python, and C++ — all implementing the same wire protocol.
+
+- **Pros**: Zero third-party dependencies. Full feature coverage. Complete control. Can be verified against official source line-by-line.
+- **Cons**: Significant upfront work. Need to understand the protocol. Ongoing maintenance when IBKR updates.
+
+**Decision**: Chosen. The official Python client was selected as the translation source because Python → TypeScript is the shortest translation distance.
+
+## Understanding the Official Distribution
+
+The TWS API is distributed as a zip file from `interactivebrokers.github.io`. It contains:
+
+```
+IBJts/
+├── source/
+│ ├── proto/ # 203 .proto files — THE protocol source of truth
+│ ├── pythonclient/ # Python client implementation
+│ ├── JavaClient/ # Java client (original, 244k lines)
+│ └── cppclient/ # C++ client
+└── samples/ # Usage examples per language
+```
+
+Key discovery: the `.proto` files are the canonical protocol definition. All language clients are generated from or aligned with these protos. IBKR distributes compiled `_pb2.py` files but also includes the raw `.proto` source — this meant we could auto-generate TypeScript protobuf bindings.
+
+### The dual protocol
+
+TWS API v10.44 supports two wire formats:
+
+1. **Legacy text protocol**: `\0`-delimited string fields, position-based. Used for 20+ years. Every field must be sent in exact order. New fields can only be appended. Version-gated with `if serverVersion >= MIN_SERVER_VER_XXX`.
+
+2. **Protobuf protocol** (v201+): Self-describing, field-number-based. Added starting with server version 201. Each message type has its own `.proto` definition. Backward-compatible by design.
+
+The client negotiates a version range at handshake. Modern TWS (v222) responds with protobuf for most messages. The protocol offset is simple: protobuf message IDs = text message ID + 200.
+
+## Translation Strategy
+
+### Source selection
+
+Python was chosen over Java because:
+- Python → TypeScript translation distance is shorter (both dynamic, similar syntax)
+- Python client is 17.5k lines vs Java's 244k lines (Java is extremely verbose)
+- Python is the most readable reference for protocol details
+
+### File structure: mirror then modularize
+
+Initial plan was to mirror the Python file structure 1:1. This worked well for data models and constants. But `client.py` (7,502 lines) and `decoder.py` (2,971 lines) were too large for AI-assisted development — agents would hit output token limits trying to translate them in one shot.
+
+**Solution**: Split by message category.
+
+```
+Python TypeScript
+client.py (7502 lines) → client/base.ts + market-data.ts + orders.ts + account.ts + historical.ts
+decoder.py (2971 lines) → decoder/base.ts + market-data.ts + orders.ts + account.ts + contract.ts + execution.ts + historical.ts + misc.ts
+```
+
+Each file stays under 500 lines. This is not just an AI constraint — it's better architecture. Changes to market data handling don't require reading order logic.
+
+### Mixin pattern for client methods
+
+Python's `EClient` is a single class with 100+ methods. In TypeScript, these are split across files using prototype extension:
+
+```typescript
+// client/market-data.ts
+export function applyMarketData(Client: typeof EClient): void {
+ Client.prototype.reqMktData = function(this: EClient, ...) { ... }
+}
+
+// client/index.ts
+applyMarketData(EClient)
+applyOrders(EClient)
+applyAccount(EClient)
+applyHistorical(EClient)
+```
+
+### Handler registration for decoder
+
+Similarly, the decoder uses a registration pattern:
+
+```typescript
+// decoder/market-data.ts
+export function applyMarketDataHandlers(decoder: Decoder): void {
+ decoder.registerText(IN.TICK_PRICE, (d, fields) => { ... })
+ decoder.registerProto(IN.TICK_PRICE, (d, buf) => { ... })
+}
+```
+
+Each handler file registers both text and protobuf handlers for its message category.
+
+## Key Adaptations from Python
+
+### Threading → Event loop
+
+Python uses a background thread (`EReader`) to read from the socket and put messages into a `queue.Queue`. The main thread polls the queue in `client.run()`.
+
+Node.js doesn't need this. Instead:
+- `socket.on('data')` accumulates bytes
+- Complete frames are extracted via `readMsg()`
+- Messages are dispatched directly to the decoder
+- No threads, no queue
+
+### `struct.pack/unpack` → `Buffer`
+
+Python: `struct.pack("!I", size)` / `struct.unpack("!I", buf[0:4])`
+TypeScript: `buf.writeUInt32BE(size)` / `buf.readUInt32BE(0)`
+
+### `next(fields)` iterator → typed decode functions
+
+Python uses a generic `decode(the_type, fields)` that calls `next()` on an iterator and converts based on type. TypeScript uses separate typed functions:
+
+```typescript
+decodeStr(fields) // → string
+decodeInt(fields) // → number
+decodeFloat(fields) // → number
+decodeBool(fields) // → boolean
+decodeDecimal(fields) // → Decimal
+```
+
+### Protobuf bindings
+
+Python's `_pb2.py` files are generated by `protoc --python_out`. We use `ts-proto` (`protoc --ts_proto_out`) to generate TypeScript equivalents from the same `.proto` files. The generated API:
+
+```typescript
+const proto = CurrentTimeProto.decode(buf) // Uint8Array → typed object
+proto.currentTime // number | undefined
+```
+
+## Testing Strategy
+
+### Unit tests (`.spec.ts`)
+
+Ported from the official Python tests (which were very thin — 447 lines total, mostly `print()` statements). We expanded significantly:
+
+- `comm.spec.ts` — Encode/decode round-trips (from Python's `test_comm.py`)
+- `utils.spec.ts` — Decode functions, formatting, validation
+- `models.spec.ts` — Data model construction and defaults
+- `order-condition.spec.ts` — Condition hierarchy + encode/decode round-trip
+- `protobuf-decode.spec.ts` — Protobuf message parsing → wrapper callback verification
+
+### E2E tests (`.e2e.spec.ts`)
+
+Integration tests against a live TWS/IB Gateway instance:
+
+- `connect.e2e.spec.ts` — Handshake, server version, nextValidId, managedAccounts, currentTime
+- `contract-details.e2e.spec.ts` — reqContractDetails("AAPL") full round-trip
+
+All e2e tests share a single TWS connection via `tests/e2e/setup.ts`. If TWS is not running, tests skip automatically (checked via TCP probe). This means `pnpm test` always succeeds regardless of environment.
+
+## What's not implemented
+
+### Protobuf request encoding (`client_utils.py`)
+
+The client currently sends all requests using the text protocol. TWS accepts this even at v222 — it's backward compatible. The protobuf request path (`client_utils.py` / `createXxxRequestProto()`) is not yet translated. This means we send text, receive protobuf. It works, but is slightly less efficient than pure protobuf.
+
+### `sync_wrapper.py`
+
+Python's synchronous wrapper (threading.Event-based request/response correlation) was not ported. Alice's adapter layer (`IbkrAccount`) will implement its own Promise-based equivalent.
+
+## Reference
+
+- Official TWS API: https://interactivebrokers.github.io/
+- Proto files: `ref/source/proto/*.proto`
+- Python client: `ref/source/pythonclient/ibapi/`
+- Python samples: `ref/samples/Python/Testbed/`
diff --git a/packages/ibkr/README.md b/packages/ibkr/README.md
new file mode 100644
index 00000000..f75f8af7
--- /dev/null
+++ b/packages/ibkr/README.md
@@ -0,0 +1,131 @@
+# @traderalice/ibkr
+
+TypeScript port of the official IBKR TWS API v10.44.01.
+
+Translated from the [official Python client](https://interactivebrokers.github.io/) — not a wrapper around a third-party library. Zero supply chain risk.
+
+## Quick Start
+
+```typescript
+import { EClient, DefaultEWrapper, Contract } from '@traderalice/ibkr'
+
+class MyWrapper extends DefaultEWrapper {
+ currentTime(time: number) {
+ console.log('Server time:', new Date(time * 1000))
+ }
+ contractDetails(reqId: number, details: ContractDetails) {
+ console.log(details.contract.symbol, details.longName)
+ }
+}
+
+const client = new EClient(new MyWrapper())
+await client.connect('127.0.0.1', 7497, 0) // paper trading
+
+client.reqCurrentTime()
+
+const contract = new Contract()
+contract.symbol = 'AAPL'
+contract.secType = 'STK'
+contract.exchange = 'SMART'
+contract.currency = 'USD'
+client.reqContractDetails(1, contract)
+```
+
+## Architecture
+
+```
+EClient ──send──► TWS/IB Gateway ──respond──► Decoder ──call──► EWrapper
+(requests) (localhost TCP) (parse) (callbacks)
+```
+
+**EClient** encodes and sends requests. **Decoder** parses responses (text or protobuf) and calls methods on your **EWrapper** implementation. You override only the callbacks you care about.
+
+### Dual Protocol
+
+TWS v201+ uses protobuf for most messages. Older versions use a text protocol (`\0`-delimited fields). Both are fully implemented. The protocol is negotiated at handshake — you don't need to think about it.
+
+## Project Structure
+
+```
+src/
+├── client/ # EClient — request encoding
+│ ├── base.ts # Connection, handshake, sendMsg
+│ ├── encode.ts # Shared contract field serialization
+│ ├── market-data.ts # reqMktData, reqTickByTick, etc.
+│ ├── orders.ts # placeOrder, cancelOrder, reqOpenOrders
+│ ├── account.ts # reqAccountSummary, reqPositions, reqPnL
+│ ├── historical.ts # reqHistoricalData, reqScanner, reqNews
+│ └── index.ts # Assembles mixins onto EClient
+│
+├── decoder/ # Decoder — response parsing
+│ ├── base.ts # Decoder class, interpret(), processProtoBuf()
+│ ├── market-data.ts # Tick, depth, market data type handlers
+│ ├── orders.ts # Order status, open/completed order handlers
+│ ├── account.ts # Account, position, PnL handlers
+│ ├── contract.ts # Contract details, symbol samples handlers
+│ ├── execution.ts # Execution, commission report handlers
+│ ├── historical.ts # Historical data, realtime bars handlers
+│ ├── misc.ts # News, scanner, verify, WSH, config handlers
+│ └── index.ts # Assembles all handler groups
+│
+├── protobuf/ # Auto-generated from .proto (not in git)
+│ └── *.ts # 203 files, generated via `pnpm generate:proto`
+│
+├── wrapper.ts # EWrapper interface + DefaultEWrapper
+├── order-decoder.ts # Version-gated order field extraction
+├── comm.ts # Message framing (length prefix + NULL fields)
+├── connection.ts # TCP socket wrapper (net.Socket)
+├── reader.ts # Socket data → framed messages
+├── utils.ts # Field decode, formatting, validation
+│
+├── contract.ts, order.ts, execution.ts, ... # Data models
+├── const.ts, errors.ts, server-versions.ts # Constants
+├── message.ts # IN/OUT message ID enums
+└── index.ts # Public API re-exports
+```
+
+### Why the split?
+
+Both `client/` and `decoder/` are split by message category (market-data, orders, account, etc.) instead of being single monolithic files. This keeps each file under 500 lines — manageable for both humans and AI-assisted development.
+
+## Reference Source
+
+`ref/` contains the official IBKR TWS API distribution (v10.44.01):
+
+- `ref/source/proto/` — 203 `.proto` files (protocol source of truth)
+- `ref/source/pythonclient/ibapi/` — Python client (translation reference)
+- `ref/samples/Python/Testbed/` — Usage examples
+
+Java/C++ sources are in `.gitignore` (available locally after extracting the TWS API zip).
+
+## Testing
+
+```bash
+pnpm test # Unit tests (56 tests, no external deps)
+pnpm test:e2e # Integration tests (needs TWS/IB Gateway running)
+pnpm test:all # Both
+```
+
+E2e tests share a single TWS connection via `tests/e2e/setup.ts`. If TWS is not running, e2e tests skip automatically.
+
+### TWS Ports
+
+| Mode | TWS | IB Gateway |
+|------|-----|------------|
+| Paper | 7497 | 4002 |
+| Live | 7496 | 4001 |
+
+Configure via env: `TWS_HOST=127.0.0.1 TWS_PORT=7497`
+
+## Protobuf Generation
+
+The `src/protobuf/` directory is auto-generated and git-ignored. To regenerate:
+
+```bash
+brew install protobuf # needs protoc
+pnpm generate:proto # runs protoc with ts-proto plugin
+```
+
+## Relationship to Official API
+
+This is a mechanical translation of the official Python `ibapi` package. Method names, field names, and message IDs are kept identical for cross-reference. When debugging, you can compare any handler against the same-named method in `ref/source/pythonclient/ibapi/`.
diff --git a/packages/ibkr/generate-proto.sh b/packages/ibkr/generate-proto.sh
new file mode 100755
index 00000000..50b05549
--- /dev/null
+++ b/packages/ibkr/generate-proto.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+# Generate TypeScript bindings from IBKR .proto files
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+PROTO_DIR="$SCRIPT_DIR/ref/source/proto"
+OUT_DIR="$SCRIPT_DIR/src/protobuf"
+PLUGIN="$SCRIPT_DIR/node_modules/.bin/protoc-gen-ts_proto"
+
+rm -rf "$OUT_DIR"
+mkdir -p "$OUT_DIR"
+
+protoc \
+ --plugin="protoc-gen-ts_proto=$PLUGIN" \
+ --ts_proto_out="$OUT_DIR" \
+ --ts_proto_opt=esModuleInterop=true \
+ --ts_proto_opt=outputTypeRegistry=false \
+ --ts_proto_opt=useExactTypes=false \
+ --proto_path="$PROTO_DIR" \
+ "$PROTO_DIR"/*.proto
+
+echo "Generated $(ls "$OUT_DIR"/*.ts 2>/dev/null | wc -l | tr -d ' ') TypeScript files in $OUT_DIR"
diff --git a/packages/ibkr/package.json b/packages/ibkr/package.json
new file mode 100644
index 00000000..59f2b765
--- /dev/null
+++ b/packages/ibkr/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "@traderalice/ibkr",
+ "version": "0.1.0",
+ "description": "TypeScript port of IBKR TWS API v10.44.01",
+ "type": "module",
+ "exports": {
+ ".": {
+ "import": "./dist/index.js",
+ "types": "./dist/index.d.ts"
+ }
+ },
+ "files": [
+ "dist"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/TraderAlice/OpenAlice.git",
+ "directory": "packages/ibkr"
+ },
+ "scripts": {
+ "build": "tsup",
+ "test": "vitest run --config vitest.config.ts",
+ "test:e2e": "vitest run --config vitest.e2e.config.ts",
+ "test:all": "vitest run --config vitest.config.ts && vitest run --config vitest.e2e.config.ts",
+ "typecheck": "tsc --noEmit",
+ "generate:proto": "bash generate-proto.sh"
+ },
+ "dependencies": {
+ "@bufbuild/protobuf": "^2.11.0",
+ "decimal.js": "^10.6.0",
+ "protobufjs": "^7.4.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22.13.4",
+ "ts-proto": "^2.11.5",
+ "tsup": "^8.4.0",
+ "typescript": "^5.7.3",
+ "vitest": "^3.0.6"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "license": "AGPL-3.0"
+}
diff --git a/packages/ibkr/ref/API_VersionNum.txt b/packages/ibkr/ref/API_VersionNum.txt
new file mode 100644
index 00000000..64fd23a4
--- /dev/null
+++ b/packages/ibkr/ref/API_VersionNum.txt
@@ -0,0 +1 @@
+API_Version=10.44.01
diff --git a/packages/ibkr/ref/samples/Python/Testbed/.gitignore b/packages/ibkr/ref/samples/Python/Testbed/.gitignore
new file mode 100644
index 00000000..ba2be52a
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/.gitignore
@@ -0,0 +1,7 @@
+tags
+__pycache__/*
+log/*
+*.log
+log.*
+core
+*.xml
diff --git a/packages/ibkr/ref/samples/Python/Testbed/AvailableAlgoParams.py b/packages/ibkr/ref/samples/Python/Testbed/AvailableAlgoParams.py
new file mode 100644
index 00000000..9f4f5ed3
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/AvailableAlgoParams.py
@@ -0,0 +1,314 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.object_implem import Object
+from ibapi.tag_value import TagValue
+from ibapi.order import Order
+
+
+class AvailableAlgoParams(Object):
+
+ # ! [scale_params]
+ @staticmethod
+ def FillScaleParams(baseOrder: Order, scaleInitLevelSize: int, scaleSubsLevelSize: int, scaleRandomPercent: bool,
+ scalePriceIncrement: float, scalePriceAdjustValue: float, scalePriceAdjustInterval: int,
+ scaleProfitOffset: float, scaleAutoReset: bool, scaleInitPosition: int, scaleInitFillQty: int):
+ baseOrder.scaleInitLevelSize = scaleInitLevelSize # Initial Component Size
+ baseOrder.scaleSubsLevelSize = scaleSubsLevelSize # Subsequent Comp. Size
+ baseOrder.scaleRandomPercent = scaleRandomPercent # Randomize size by +/-55%
+ baseOrder.scalePriceIncrement = scalePriceIncrement # Price Increment
+
+ # Auto Price adjustment
+ baseOrder.scalePriceAdjustValue = scalePriceAdjustValue # starting price by
+ baseOrder.scalePriceAdjustInterval = scalePriceAdjustInterval # in seconds
+
+ # Profit Orders
+ baseOrder.scaleProfitOffset = scaleProfitOffset # Create profit taking order Profit Offset
+ baseOrder.scaleAutoReset = scaleAutoReset # Restore size after taking profit
+ baseOrder.scaleInitPosition = scaleInitPosition # Initial Position
+ baseOrder.scaleInitFillQty = scaleInitFillQty # Filled initial Component Size
+ # ! [scale_params]
+
+ # ! [arrivalpx_params]
+ @staticmethod
+ def FillArrivalPriceParams(baseOrder: Order, maxPctVol: float,
+ riskAversion: str, startTime: str, endTime: str,
+ forceCompletion: bool, allowPastTime: bool):
+ baseOrder.algoStrategy = "ArrivalPx"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("maxPctVol", maxPctVol))
+ baseOrder.algoParams.append(TagValue("riskAversion", riskAversion))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("forceCompletion",
+ int(forceCompletion)))
+ baseOrder.algoParams.append(TagValue("allowPastEndTime",
+ int(allowPastTime)))
+
+
+ # ! [arrivalpx_params]
+
+
+ # ! [darkice_params]
+ @staticmethod
+ def FillDarkIceParams(baseOrder: Order, displaySize: int, startTime: str,
+ endTime: str, allowPastEndTime: bool):
+ baseOrder.algoStrategy = "DarkIce"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("displaySize", displaySize))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("allowPastEndTime",
+ int(allowPastEndTime)))
+
+
+ # ! [darkice_params]
+
+
+ # ! [pctvol_params]
+ @staticmethod
+ def FillPctVolParams(baseOrder: Order, pctVol: float, startTime: str,
+ endTime: str, noTakeLiq: bool):
+ baseOrder.algoStrategy = "PctVol"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("pctVol", pctVol))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("noTakeLiq", int(noTakeLiq)))
+
+
+ # ! [pctvol_params]
+
+
+ # ! [twap_params]
+ @staticmethod
+ def FillTwapParams(baseOrder: Order, strategyType: str, startTime: str,
+ endTime: str, allowPastEndTime: bool):
+ baseOrder.algoStrategy = "Twap"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("strategyType", strategyType))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("allowPastEndTime",
+ int(allowPastEndTime)))
+
+ # ! [twap_params]
+
+
+ # ! [vwap_params]
+ @staticmethod
+ def FillVwapParams(baseOrder: Order, maxPctVol: float, startTime: str,
+ endTime: str, allowPastEndTime: bool, noTakeLiq: bool):
+ baseOrder.algoStrategy = "Vwap"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("maxPctVol", maxPctVol))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("allowPastEndTime",
+ int(allowPastEndTime)))
+ baseOrder.algoParams.append(TagValue("noTakeLiq", int(noTakeLiq)))
+
+
+ # ! [vwap_params]
+
+
+ # ! [ad_params]
+ @staticmethod
+ def FillAccumulateDistributeParams(baseOrder: Order, componentSize: int,
+ timeBetweenOrders: int, randomizeTime20: bool, randomizeSize55: bool,
+ giveUp: int, catchUp: bool, waitForFill: bool, startTime: str,
+ endTime: str):
+ baseOrder.algoStrategy = "AD"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("componentSize", componentSize))
+ baseOrder.algoParams.append(TagValue("timeBetweenOrders", timeBetweenOrders))
+ baseOrder.algoParams.append(TagValue("randomizeTime20",
+ int(randomizeTime20)))
+ baseOrder.algoParams.append(TagValue("randomizeSize55",
+ int(randomizeSize55)))
+ baseOrder.algoParams.append(TagValue("giveUp", giveUp))
+ baseOrder.algoParams.append(TagValue("catchUp", int(catchUp)))
+ baseOrder.algoParams.append(TagValue("waitForFill", int(waitForFill)))
+ baseOrder.algoParams.append(TagValue("activeTimeStart", startTime))
+ baseOrder.algoParams.append(TagValue("activeTimeEnd", endTime))
+
+ # ! [ad_params]
+
+
+ # ! [balanceimpactrisk_params]
+ @staticmethod
+ def FillBalanceImpactRiskParams(baseOrder: Order, maxPctVol: float,
+ riskAversion: str, forceCompletion: bool):
+ baseOrder.algoStrategy = "BalanceImpactRisk"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("maxPctVol", maxPctVol))
+ baseOrder.algoParams.append(TagValue("riskAversion", riskAversion))
+ baseOrder.algoParams.append(TagValue("forceCompletion",
+ int(forceCompletion)))
+
+ # ! [balanceimpactrisk_params]
+
+
+ # ! [minimpact_params]
+ @staticmethod
+ def FillMinImpactParams(baseOrder: Order, maxPctVol: float):
+ baseOrder.algoStrategy = "MinImpact"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("maxPctVol", maxPctVol))
+
+ # ! [minimpact_params]
+
+
+ # ! [adaptive_params]
+ @staticmethod
+ def FillAdaptiveParams(baseOrder: Order, priority: str):
+ baseOrder.algoStrategy = "Adaptive"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("adaptivePriority", priority))
+
+ # ! [adaptive_params]
+
+ # ! [closepx_params]
+ @staticmethod
+ def FillClosePriceParams(baseOrder: Order, maxPctVol: float, riskAversion: str,
+ startTime: str, forceCompletion: bool):
+ baseOrder.algoStrategy = "ClosePx"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("maxPctVol", maxPctVol))
+ baseOrder.algoParams.append(TagValue("riskAversion", riskAversion))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("forceCompletion", int(forceCompletion)))
+
+
+ # ! [closepx_params]
+
+
+ # ! [pctvolpx_params]
+ @staticmethod
+ def FillPriceVariantPctVolParams(baseOrder: Order, pctVol: float,
+ deltaPctVol: float, minPctVol4Px: float,
+ maxPctVol4Px: float, startTime: str,
+ endTime: str, noTakeLiq: bool):
+ baseOrder.algoStrategy = "PctVolPx"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("pctVol", pctVol))
+ baseOrder.algoParams.append(TagValue("deltaPctVol", deltaPctVol))
+ baseOrder.algoParams.append(TagValue("minPctVol4Px", minPctVol4Px))
+ baseOrder.algoParams.append(TagValue("maxPctVol4Px", maxPctVol4Px))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("noTakeLiq", int(noTakeLiq)))
+
+
+ # ! [pctvolpx_params]
+
+
+ # ! [pctvolsz_params]
+ @staticmethod
+ def FillSizeVariantPctVolParams(baseOrder: Order, startPctVol: float,
+ endPctVol: float, startTime: str,
+ endTime: str, noTakeLiq: bool):
+ baseOrder.algoStrategy = "PctVolSz"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("startPctVol", startPctVol))
+ baseOrder.algoParams.append(TagValue("endPctVol", endPctVol))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("noTakeLiq", int(noTakeLiq)))
+
+
+ # ! [pctvolsz_params]
+
+
+ # ! [pctvoltm_params]
+ @staticmethod
+ def FillTimeVariantPctVolParams(baseOrder: Order, startPctVol: float,
+ endPctVol: float, startTime: str,
+ endTime: str, noTakeLiq: bool):
+ baseOrder.algoStrategy = "PctVolTm"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("startPctVol", startPctVol))
+ baseOrder.algoParams.append(TagValue("endPctVol", endPctVol))
+ baseOrder.algoParams.append(TagValue("startTime", startTime))
+ baseOrder.algoParams.append(TagValue("endTime", endTime))
+ baseOrder.algoParams.append(TagValue("noTakeLiq", int(noTakeLiq)))
+
+ # ! [pctvoltm_params]
+
+ # ! [jefferies_vwap_params]
+ @staticmethod
+ def FillJefferiesVWAPParams(baseOrder: Order, startTime: str,
+ endTime: str, relativeLimit: float,
+ maxVolumeRate: float, excludeAuctions: str,
+ triggerPrice: float, wowPrice: float,
+ minFillSize: int, wowOrderPct: float,
+ wowMode: str, isBuyBack: bool, wowReference: str):
+ # must be direct-routed to "JEFFALGO"
+ baseOrder.algoStrategy = "VWAP"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("StartTime", startTime))
+ baseOrder.algoParams.append(TagValue("EndTime", endTime))
+ baseOrder.algoParams.append(TagValue("RelativeLimit", relativeLimit))
+ baseOrder.algoParams.append(TagValue("MaxVolumeRate", maxVolumeRate))
+ baseOrder.algoParams.append(TagValue("ExcludeAuctions", excludeAuctions))
+ baseOrder.algoParams.append(TagValue("TriggerPrice", triggerPrice))
+ baseOrder.algoParams.append(TagValue("WowPrice", wowPrice))
+ baseOrder.algoParams.append(TagValue("MinFillSize", minFillSize))
+ baseOrder.algoParams.append(TagValue("WowOrderPct", wowOrderPct))
+ baseOrder.algoParams.append(TagValue("WowMode", wowMode))
+ baseOrder.algoParams.append(TagValue("IsBuyBack", int(isBuyBack)))
+ baseOrder.algoParams.append(TagValue("WowReference", wowReference))
+ # ! [jefferies_vwap_params]
+
+ # ! [csfb_inline_params]
+ @staticmethod
+ def FillCSFBInlineParams(baseOrder: Order, startTime: str,
+ endTime: str, execStyle: str,
+ minPercent: int, maxPercent: int,
+ displaySize: int, auction: str,
+ blockFinder: bool, blockPrice: float,
+ minBlockSize: int, maxBlockSize: int, iWouldPrice: float):
+ # must be direct-routed to "CSFBALGO"
+ baseOrder.algoStrategy = "INLINE"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("StartTime", startTime))
+ baseOrder.algoParams.append(TagValue("EndTime", endTime))
+ baseOrder.algoParams.append(TagValue("ExecStyle", execStyle))
+ baseOrder.algoParams.append(TagValue("MinPercent", minPercent))
+ baseOrder.algoParams.append(TagValue("MaxPercent", maxPercent))
+ baseOrder.algoParams.append(TagValue("DisplaySize", displaySize))
+ baseOrder.algoParams.append(TagValue("Auction", auction))
+ baseOrder.algoParams.append(TagValue("BlockFinder", int(blockFinder)))
+ baseOrder.algoParams.append(TagValue("BlockPrice", blockPrice))
+ baseOrder.algoParams.append(TagValue("MinBlockSize", minBlockSize))
+ baseOrder.algoParams.append(TagValue("MaxBlockSize", maxBlockSize))
+ baseOrder.algoParams.append(TagValue("IWouldPrice", iWouldPrice))
+ # ! [csfb_inline_params]
+
+ # ! [qbalgo_strobe_params]
+ @staticmethod
+ def FillQBAlgoInLineParams(baseOrder: Order, startTime: str,
+ endTime: str, duration: float,
+ benchmark: str, percentVolume: float,
+ noCleanUp: bool):
+ # must be direct-routed to "QBALGO"
+ baseOrder.algoStrategy = "STROBE"
+ baseOrder.algoParams = []
+ baseOrder.algoParams.append(TagValue("StartTime", startTime))
+ baseOrder.algoParams.append(TagValue("EndTime", endTime))
+ #This example uses endTime instead of duration
+ #baseOrder.algoParams.append(TagValue("Duration", str(duration)))
+ baseOrder.algoParams.append(TagValue("Benchmark", benchmark))
+ baseOrder.algoParams.append(TagValue("PercentVolume", str(percentVolume)))
+ baseOrder.algoParams.append(TagValue("NoCleanUp", int(noCleanUp)))
+ # ! [qbalgo_strobe_params]
+
+
+def Test():
+ av = AvailableAlgoParams() # @UnusedVariable
+
+
+if "__main__" == __name__:
+ Test()
diff --git a/packages/ibkr/ref/samples/Python/Testbed/ConfigSamples.py b/packages/ibkr/ref/samples/Python/Testbed/ConfigSamples.py
new file mode 100644
index 00000000..74d0c92a
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/ConfigSamples.py
@@ -0,0 +1,104 @@
+"""
+Copyright (C) 2026 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.protobuf.UpdateConfigRequest_pb2 import UpdateConfigRequest as UpdateConfigRequestProto
+from ibapi.protobuf.ApiConfig_pb2 import ApiConfig as ApiConfigProto
+from ibapi.protobuf.ApiSettingsConfig_pb2 import ApiSettingsConfig as ApiSettingsConfigProto
+from ibapi.protobuf.OrdersConfig_pb2 import OrdersConfig as OrdersConfigProto
+from ibapi.protobuf.OrdersSmartRoutingConfig_pb2 import OrdersSmartRoutingConfig as OrdersSmartRoutingConfigProto
+from ibapi.protobuf.MessageConfig_pb2 import MessageConfig as MessageConfigProto
+from ibapi.protobuf.UpdateConfigWarning_pb2 import UpdateConfigWarning as UpdateConfigWarningProto
+
+class ConfigSamples:
+
+ @staticmethod
+ def UpdateConfigApiSettings(reqId: int) -> UpdateConfigRequestProto:
+ #! [UpdateApiSettingsConfig]
+ updateConfigRequestProto = UpdateConfigRequestProto()
+ apiConfigProto = ApiConfigProto()
+ apiSettingsConfigProto = ApiSettingsConfigProto()
+ apiSettingsConfigProto.totalQuantityForMutualFunds = True
+ apiSettingsConfigProto.downloadOpenOrdersOnConnection = True
+ apiSettingsConfigProto.includeVirtualFxPositions = True
+ apiSettingsConfigProto.prepareDailyPnL = True
+ apiSettingsConfigProto.sendStatusUpdatesForVolatilityOrders = True
+ apiSettingsConfigProto.encodeApiMessages = "osCodePage"
+ apiSettingsConfigProto.socketPort = 7497
+ apiSettingsConfigProto.useNegativeAutoRange = True
+ apiSettingsConfigProto.createApiMessageLogFile = True
+ apiSettingsConfigProto.includeMarketDataInLogFile = True
+ apiSettingsConfigProto.exposeTradingScheduleToApi = True
+ apiSettingsConfigProto.splitInsuredDepositFromCashBalance = True
+ apiSettingsConfigProto.sendZeroPositionsForTodayOnly = True
+ apiSettingsConfigProto.useAccountGroupsWithAllocationMethods = True
+ apiSettingsConfigProto.loggingLevel = "error"
+ apiSettingsConfigProto.masterClientId = 3
+ apiSettingsConfigProto.bulkDataTimeout = 25
+ apiSettingsConfigProto.componentExchSeparator = "#"
+ apiSettingsConfigProto.roundAccountValuesToNearestWholeNumber = True
+ apiSettingsConfigProto.showAdvancedOrderRejectInUi = True
+ apiSettingsConfigProto.rejectMessagesAboveMaxRate = True
+ apiSettingsConfigProto.maintainConnectionOnIncorrectFields = True
+ apiSettingsConfigProto.compatibilityModeNasdaqStocks = True
+ apiSettingsConfigProto.sendInstrumentTimezone = "utc"
+ apiSettingsConfigProto.sendForexDataInCompatibilityMode = True
+ apiSettingsConfigProto.maintainAndResubmitOrdersOnReconnect = True
+ apiSettingsConfigProto.historicalDataMaxSize = 4
+ apiSettingsConfigProto.autoReportNettingEventContractTrades = True
+ apiSettingsConfigProto.optionExerciseRequestType = "final"
+ apiSettingsConfigProto.trustedIPs.append("127.0.0.1")
+
+ apiConfigProto.settings.CopyFrom(apiSettingsConfigProto)
+ updateConfigRequestProto.reqId = reqId
+ updateConfigRequestProto.api.CopyFrom(apiConfigProto)
+ #! [UpdateApiSettingsConfig]
+ return updateConfigRequestProto
+
+ @staticmethod
+ def UpdateOrdersConfig(reqId: int) -> UpdateConfigRequestProto:
+ #! [UpdateOrderConfig]
+ updateConfigRequestProto = UpdateConfigRequestProto()
+ ordersConfigProto = OrdersConfigProto()
+ ordersSmartRoutingConfigProto = OrdersSmartRoutingConfigProto()
+ ordersSmartRoutingConfigProto.seekPriceImprovement = True
+ ordersSmartRoutingConfigProto.doNotRouteToDarkPools = True
+ ordersConfigProto.smartRouting.CopyFrom(ordersSmartRoutingConfigProto)
+ updateConfigRequestProto.reqId = reqId
+ updateConfigRequestProto.orders.CopyFrom(ordersConfigProto)
+ #! [UpdateOrderConfig]
+ return updateConfigRequestProto
+
+ @staticmethod
+ def UpdateMessageConfigConfirmMandatoryCapPriceAccepted(reqId: int) -> UpdateConfigRequestProto:
+ #! [UpdateMessageConfigConfirmMandatoryCapPriceAccepted]
+ updateConfigRequestProto = UpdateConfigRequestProto()
+ messageConfigProto = MessageConfigProto()
+ messageConfigProto.id = 131
+ messageConfigProto.enabled = False
+ updateConfigRequestProto.reqId = reqId
+ updateConfigRequestProto.messages.append(messageConfigProto)
+ updateConfigWarningProto = UpdateConfigWarningProto()
+ updateConfigWarningProto.messageId = 131
+ updateConfigRequestProto.acceptedWarnings.append(updateConfigWarningProto)
+ #! [UpdateMessageConfigConfirmMandatoryCapPriceAccepted]
+ return updateConfigRequestProto
+
+ @staticmethod
+ def UpdateConfigOrderIdReset(reqId: int) -> UpdateConfigRequestProto:
+ #! [ UpdateConfigOrderIdReset]
+ updateConfigRequestProto = UpdateConfigRequestProto()
+ updateConfigRequestProto.reqId = reqId
+ updateConfigRequestProto.resetAPIOrderSequence = True
+ #! [ UpdateConfigOrderIdReset]
+ return updateConfigRequestProto
+
+
+def Test():
+ from ibapi.utils import ExerciseStaticMethods
+ ExerciseStaticMethods(ConfigSamples)
+
+if "__main__" == __name__:
+ Test()
+
\ No newline at end of file
diff --git a/packages/ibkr/ref/samples/Python/Testbed/ContractSamples.py b/packages/ibkr/ref/samples/Python/Testbed/ContractSamples.py
new file mode 100644
index 00000000..3da49b33
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/ContractSamples.py
@@ -0,0 +1,770 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.contract import * # @UnusedWildImport
+
+
+class ContractSamples:
+
+ """ Usually, the easiest way to define a Stock/CASH contract is through
+ these four attributes. """
+
+ @staticmethod
+ def EurGbpFx():
+ #! [cashcontract]
+ contract = Contract()
+ contract.symbol = "EUR"
+ contract.secType = "CASH"
+ contract.currency = "GBP"
+ contract.exchange = "IDEALPRO"
+ #! [cashcontract]
+ return contract
+
+
+ @staticmethod
+ def Index():
+ #! [indcontract]
+ contract = Contract()
+ contract.symbol = "DAX"
+ contract.secType = "IND"
+ contract.currency = "EUR"
+ contract.exchange = "EUREX"
+ #! [indcontract]
+ return contract
+
+
+ @staticmethod
+ def CFD():
+ #! [cfdcontract]
+ contract = Contract()
+ contract.symbol = "IBDE30"
+ contract.secType = "CFD"
+ contract.currency = "EUR"
+ contract.exchange = "SMART"
+ #! [cfdcontract]
+ return contract
+
+
+ @staticmethod
+ def EuropeanStock():
+ contract = Contract()
+ contract.symbol = "BMW"
+ contract.secType = "STK"
+ contract.currency = "EUR"
+ contract.exchange = "SMART"
+ contract.primaryExchange = "IBIS"
+ return contract
+
+ @staticmethod
+ def EuropeanStock2():
+ contract = Contract()
+ contract.symbol = "NOKIA"
+ contract.secType = "STK"
+ contract.currency = "EUR"
+ contract.exchange = "SMART"
+ contract.primaryExchange = "HEX"
+ return contract
+
+ @staticmethod
+ def OptionAtIse():
+ contract = Contract()
+ contract.symbol = "COF"
+ contract.secType = "OPT"
+ contract.currency = "USD"
+ contract.exchange = "ISE"
+ contract.lastTradeDateOrContractMonth = "20190315"
+ contract.right = "P"
+ contract.strike = 105
+ contract.multiplier = "100"
+ return contract
+
+
+ @staticmethod
+ def BondWithCusip():
+ #! [bondwithcusip]
+ contract = Contract()
+ # enter CUSIP as symbol
+ contract.symbol= "449276AA2"
+ contract.secType = "BOND"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ #! [bondwithcusip]
+ return contract
+
+
+ @staticmethod
+ def Bond():
+ #! [bond]
+ contract = Contract()
+ contract.conId = 456467716
+ contract.exchange = "SMART"
+ #! [bond]
+ return contract
+
+
+ @staticmethod
+ def MutualFund():
+ #! [fundcontract]
+ contract = Contract()
+ contract.symbol = "VINIX"
+ contract.secType = "FUND"
+ contract.exchange = "FUNDSERV"
+ contract.currency = "USD"
+ #! [fundcontract]
+ return contract
+
+
+ @staticmethod
+ def Commodity():
+ #! [commoditycontract]
+ contract = Contract()
+ contract.symbol = "XAUUSD"
+ contract.secType = "CMDTY"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ #! [commoditycontract]
+ return contract
+
+
+ @staticmethod
+ def USStock():
+ #! [stkcontract]
+ contract = Contract()
+ contract.symbol = "SPY"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "ARCA"
+ #! [stkcontract]
+ return contract
+
+
+ @staticmethod
+ def USStockWithPrimaryExch():
+ #! [stkcontractwithprimary]
+ contract = Contract()
+ contract.symbol = "SPY"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ contract.primaryExchange = "ARCA"
+ #! [stkcontractwithprimary]
+ return contract
+
+
+ @staticmethod
+ def USStockAtSmart():
+ contract = Contract()
+ contract.symbol = "IBM"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ return contract
+
+ @staticmethod
+ def etf():
+ contract = Contract()
+ contract.symbol = "QQQ"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ return contract
+
+ @staticmethod
+ def USOptionContract():
+ #! [optcontract_us]
+ contract = Contract()
+ contract.symbol = "GOOG"
+ contract.secType = "OPT"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ contract.lastTradeDateOrContractMonth = "20190315"
+ contract.strike = 1180
+ contract.right = "C"
+ contract.multiplier = "100"
+ #! [optcontract_us]
+ return contract
+
+
+ @staticmethod
+ def OptionAtBOX():
+ #! [optcontract]
+ contract = Contract()
+ contract.symbol = "GOOG"
+ contract.secType = "OPT"
+ contract.exchange = "BOX"
+ contract.currency = "USD"
+ contract.lastTradeDateOrContractMonth = "20190315"
+ contract.strike = 1180
+ contract.right = "C"
+ contract.multiplier = "100"
+ #! [optcontract]
+ return contract
+
+
+ """ Option contracts require far more information since there are many
+ contracts having the exact same attributes such as symbol, currency,
+ strike, etc. This can be overcome by adding more details such as the
+ trading class"""
+
+ @staticmethod
+ def OptionWithTradingClass():
+ #! [optcontract_tradingclass]
+ contract = Contract()
+ contract.symbol = "SANT"
+ contract.secType = "OPT"
+ contract.exchange = "MEFFRV"
+ contract.currency = "EUR"
+ contract.lastTradeDateOrContractMonth = "20190621"
+ contract.strike = 7.5
+ contract.right = "C"
+ contract.multiplier = "100"
+ contract.tradingClass = "SANEU"
+ #! [optcontract_tradingclass]
+ return contract
+
+
+ """ Using the contract's own symbol (localSymbol) can greatly simplify a
+ contract description """
+
+ @staticmethod
+ def OptionWithLocalSymbol():
+ #! [optcontract_localsymbol]
+ contract = Contract()
+ #Watch out for the spaces within the local symbol!
+ contract.localSymbol = "P BMW 20221216 72 M"
+ contract.secType = "OPT"
+ contract.exchange = "EUREX"
+ contract.currency = "EUR"
+ #! [optcontract_localsymbol]
+ return contract
+
+ """ Dutch Warrants (IOPTs) can be defined using the local symbol or conid
+ """
+
+ @staticmethod
+ def DutchWarrant():
+ #! [ioptcontract]
+ contract = Contract()
+ contract.localSymbol = "B881G"
+ contract.secType = "IOPT"
+ contract.exchange = "SBF"
+ contract.currency = "EUR"
+ #! [ioptcontract]
+ return contract
+
+ """ Future contracts also require an expiration date but are less
+ complicated than options."""
+
+ @staticmethod
+ def SimpleFuture():
+ #! [futcontract]
+ contract = Contract()
+ contract.symbol = "ES"
+ contract.secType = "FUT"
+ contract.exchange = "CME"
+ contract.currency = "USD"
+ contract.lastTradeDateOrContractMonth = "202503"
+ #! [futcontract]
+ return contract
+
+
+ """Rather than giving expiration dates we can also provide the local symbol
+ attributes such as symbol, currency, strike, etc. """
+
+ @staticmethod
+ def FutureWithLocalSymbol():
+ #! [futcontract_local_symbol]
+ contract = Contract()
+ contract.secType = "FUT"
+ contract.exchange = "EUREX"
+ contract.currency = "EUR"
+ contract.localSymbol = "FGBL MAR 23"
+ #! [futcontract_local_symbol]
+ return contract
+
+
+ @staticmethod
+ def FutureWithMultiplier():
+ #! [futcontract_multiplier]
+ contract = Contract()
+ contract.symbol = "DAX"
+ contract.secType = "FUT"
+ contract.exchange = "EUREX"
+ contract.currency = "EUR"
+ contract.lastTradeDateOrContractMonth = "202303"
+ contract.multiplier = "1"
+ #! [futcontract_multiplier]
+ return contract
+
+
+ """ Note the space in the symbol! """
+
+ @staticmethod
+ def WrongContract():
+ contract = Contract()
+ contract.symbol = " IJR "
+ contract.conId = 9579976
+ contract.secType = "STK"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ return contract
+
+ @staticmethod
+ def FuturesOnOptions():
+ #! [fopcontract]
+ contract = Contract()
+ contract.symbol = "GBL"
+ contract.secType = "FOP"
+ contract.exchange = "EUREX"
+ contract.currency = "EUR"
+ contract.lastTradeDateOrContractMonth = "20230224"
+ contract.strike = 138
+ contract.right = "C"
+ contract.multiplier = "1000"
+ #! [fopcontract]
+ return contract
+
+ @staticmethod
+ def Warrants():
+ #! [warcontract]
+ contract = Contract()
+ contract.symbol = "GOOG"
+ contract.secType = "WAR"
+ contract.exchange = "FWB"
+ contract.currency = "EUR"
+ contract.lastTradeDateOrContractMonth = "20201117"
+ contract.strike = 1500.0
+ contract.right = "C"
+ contract.multiplier = "0.01"
+ #! [warcontract]
+ return contract
+
+ """ It is also possible to define contracts based on their ISIN (IBKR STK
+ sample). """
+
+ @staticmethod
+ def ByISIN():
+ contract = Contract()
+ contract.secIdType = "ISIN"
+ contract.secId = "US45841N1072"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ contract.secType = "STK"
+ return contract
+
+
+ """ Or their conId (EUR.uSD sample).
+ Note: passing a contract containing the conId can cause problems if one of
+ the other provided attributes does not match 100% with what is in IB's
+ database. This is particularly important for contracts such as Bonds which
+ may change their description from one day to another.
+ If the conId is provided, it is best not to give too much information as
+ in the example below. """
+
+ @staticmethod
+ def ByConId():
+ contract = Contract()
+ contract.secType = "CASH"
+ contract.conId = 12087792
+ contract.exchange = "IDEALPRO"
+ return contract
+
+
+ """ Ambiguous contracts are great to use with reqContractDetails. This way
+ you can query the whole option chain for an underlying. Bear in mind that
+ there are pacing mechanisms in place which will delay any further responses
+ from the TWS to prevent abuse. """
+
+ @staticmethod
+ def OptionForQuery():
+ #! [optionforquery]
+ contract = Contract()
+ contract.symbol = "FISV"
+ contract.secType = "OPT"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ #! [optionforquery]
+ return contract
+
+
+ @staticmethod
+ def OptionComboContract():
+ #! [bagoptcontract]
+ contract = Contract()
+ contract.symbol = "DBK"
+ contract.secType = "BAG"
+ contract.currency = "EUR"
+ contract.exchange = "EUREX"
+
+ leg1 = ComboLeg()
+ leg1.conId = 577164786 #DBK Jun21'24 2 CALL @EUREX
+ leg1.ratio = 1
+ leg1.action = "BUY"
+ leg1.exchange = "EUREX"
+
+ leg2 = ComboLeg()
+ leg2.conId = 577164767 #DBK Dec15'23 2 CALL @EUREX
+ leg2.ratio = 1
+ leg2.action = "SELL"
+ leg2.exchange = "EUREX"
+
+ contract.comboLegs = []
+ contract.comboLegs.append(leg1)
+ contract.comboLegs.append(leg2)
+ #! [bagoptcontract]
+ return contract
+
+
+ """ STK Combo contract
+ Leg 1: 43645865 - IBKR's STK
+ Leg 2: 9408 - McDonald's STK """
+
+ @staticmethod
+ def StockComboContract():
+ #! [bagstkcontract]
+ contract = Contract()
+ contract.symbol = "IBKR,MCD"
+ contract.secType = "BAG"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+
+ leg1 = ComboLeg()
+ leg1.conId = 43645865#IBKR STK
+ leg1.ratio = 1
+ leg1.action = "BUY"
+ leg1.exchange = "SMART"
+
+ leg2 = ComboLeg()
+ leg2.conId = 9408#MCD STK
+ leg2.ratio = 1
+ leg2.action = "SELL"
+ leg2.exchange = "SMART"
+
+ contract.comboLegs = []
+ contract.comboLegs.append(leg1)
+ contract.comboLegs.append(leg2)
+ #! [bagstkcontract]
+ return contract
+
+
+ """ CBOE Volatility Index Future combo contract """
+
+ @staticmethod
+ def FutureComboContract():
+ #! [bagfutcontract]
+ contract = Contract()
+ contract.symbol = "VIX"
+ contract.secType = "BAG"
+ contract.currency = "USD"
+ contract.exchange = "CFE"
+
+ leg1 = ComboLeg()
+ leg1.conId = 326501438 # VIX FUT 201903
+ leg1.ratio = 1
+ leg1.action = "BUY"
+ leg1.exchange = "CFE"
+
+ leg2 = ComboLeg()
+ leg2.conId = 323072528 # VIX FUT 2019049
+ leg2.ratio = 1
+ leg2.action = "SELL"
+ leg2.exchange = "CFE"
+
+ contract.comboLegs = []
+ contract.comboLegs.append(leg1)
+ contract.comboLegs.append(leg2)
+ #! [bagfutcontract]
+ return contract
+
+ @staticmethod
+ def SmartFutureComboContract():
+ #! [smartfuturespread]
+ contract = Contract()
+ contract.symbol = "WTI" # WTI,COIL spread. Symbol can be defined as first leg symbol ("WTI") or currency ("USD")
+ contract.secType = "BAG"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+
+ leg1 = ComboLeg()
+ leg1.conId = 55928698 # WTI future June 2017
+ leg1.ratio = 1
+ leg1.action = "BUY"
+ leg1.exchange = "IPE"
+
+ leg2 = ComboLeg()
+ leg2.conId = 55850663 # COIL future June 2017
+ leg2.ratio = 1
+ leg2.action = "SELL"
+ leg2.exchange = "IPE"
+
+ contract.comboLegs = []
+ contract.comboLegs.append(leg1)
+ contract.comboLegs.append(leg2)
+ #! [smartfuturespread]
+ return contract
+
+ @staticmethod
+ def InterCmdtyFuturesContract():
+ #! [intcmdfutcontract]
+ contract = Contract()
+ contract.symbol = "COL.WTI" #symbol is 'local symbol' of intercommodity spread.
+ contract.secType = "BAG"
+ contract.currency = "USD"
+ contract.exchange = "IPE"
+
+ leg1 = ComboLeg()
+ leg1.conId = 183405603 #WTI�Dec'23�@IPE
+ leg1.ratio = 1
+ leg1.action = "BUY"
+ leg1.exchange = "IPE"
+
+ leg2 = ComboLeg()
+ leg2.conId = 254011009 #COIL�Dec'23�@IPE
+ leg2.ratio = 1
+ leg2.action = "SELL"
+ leg2.exchange = "IPE"
+
+ contract.comboLegs = []
+ contract.comboLegs.append(leg1)
+ contract.comboLegs.append(leg2)
+ #! [intcmdfutcontract]
+ return contract
+
+
+ @staticmethod
+ def NewsFeedForQuery():
+ #! [newsfeedforquery]
+ contract = Contract()
+ contract.secType = "NEWS"
+ contract.exchange = "BRFG" #Briefing Trader
+ #! [newsfeedforquery]
+ return contract
+
+
+ @staticmethod
+ def BTbroadtapeNewsFeed():
+ #! [newscontractbt]
+ contract = Contract()
+ contract.symbol = "BRF:BRF_ALL"
+ contract.secType = "NEWS"
+ contract.exchange = "BRF"
+ #! [newscontractbt]
+ return contract
+
+
+ @staticmethod
+ def BZbroadtapeNewsFeed():
+ #! [newscontractbz]
+ contract = Contract()
+ contract.symbol = "BZ:BZ_ALL"
+ contract.secType = "NEWS"
+ contract.exchange = "BZ"
+ #! [newscontractbz]
+ return contract
+
+
+ @staticmethod
+ def FLYbroadtapeNewsFeed():
+ #! [newscontractfly]
+ contract = Contract()
+ contract.symbol = "FLY:FLY_ALL"
+ contract.secType = "NEWS"
+ contract.exchange = "FLY"
+ #! [newscontractfly]
+ return contract
+
+
+ @staticmethod
+ def ContFut():
+ #! [continuousfuturescontract]
+ contract = Contract()
+ contract.symbol = "GBL"
+ contract.secType = "CONTFUT"
+ contract.exchange = "EUREX"
+ #! [continuousfuturescontract]
+ return contract
+
+ @staticmethod
+ def ContAndExpiringFut():
+ #! [contandexpiringfut]
+ contract = Contract()
+ contract.symbol = "GBL"
+ contract.secType = "FUT+CONTFUT"
+ contract.exchange = "EUREX"
+ #! [contandexpiringfut]
+ return contract
+
+ @staticmethod
+ def JefferiesContract():
+ #! [jefferies_contract]
+ contract = Contract()
+ contract.symbol = "AAPL"
+ contract.secType = "STK"
+ contract.exchange = "JEFFALGO"
+ contract.currency = "USD"
+ #! [jefferies_contract]
+ return contract
+
+ @staticmethod
+ def CSFBContract():
+ #! [csfb_contract]
+ contract = Contract()
+ contract.symbol = "IBKR"
+ contract.secType = "STK"
+ contract.exchange = "CSFBALGO"
+ contract.currency = "USD"
+ #! [csfb_contract]
+ return contract
+
+ @staticmethod
+ def USStockCFD():
+ # ! [usstockcfd_conract]
+ contract = Contract()
+ contract.symbol = "IBM"
+ contract.secType = "CFD"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ # ! [usstockcfd_conract]
+ return contract
+
+ @staticmethod
+ def EuropeanStockCFD():
+ # ! [europeanstockcfd_contract]
+ contract = Contract()
+ contract.symbol = "BMW"
+ contract.secType = "CFD"
+ contract.currency = "EUR"
+ contract.exchange = "SMART"
+ # ! [europeanstockcfd_contract]
+ return contract
+
+ @staticmethod
+ def CashCFD():
+ # ! [cashcfd_contract]
+ contract = Contract()
+ contract.symbol = "EUR"
+ contract.secType = "CFD"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ # ! [cashcfd_contract]
+ return contract
+
+ @staticmethod
+ def QBAlgoContract():
+ # ! [qbalgo_contract]
+ contract = Contract()
+ contract.symbol = "ES"
+ contract.secType = "FUT"
+ contract.exchange = "QBALGO"
+ contract.currency = "USD"
+ contract.lastTradeDateOrContractMonth = "202003"
+ # ! [qbalgo_contract]
+ return contract
+
+ @staticmethod
+ def IBKRATSContract():
+ # ! [ibkrats_contract]
+ contract = Contract()
+ contract.symbol = "SPY"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "IBKRATS"
+ # ! [ibkrats_contract]
+ return contract
+
+ @staticmethod
+ def CryptoContract():
+ # ! [crypto_contract]
+ contract = Contract()
+ contract.symbol = "ETH"
+ contract.secType = "CRYPTO"
+ contract.currency = "USD"
+ contract.exchange = "PAXOS"
+ # ! [crypto_contract]
+ return contract
+
+ @staticmethod
+ def StockWithIPOPrice():
+ # ! [stock_with_IPO_price]
+ contract = Contract()
+ contract.symbol = "EMCGU"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ # ! [stock_with_IPO_price]
+ return contract
+
+ @staticmethod
+ def ByFIGI():
+ # ! [ByFIGI]
+ contract = Contract()
+ contract.secIdType = "FIGI"
+ contract.secId = "BBG000B9XRY4"
+ contract.exchange = "SMART"
+ # ! [ByFIGI]
+ return contract
+
+ @staticmethod
+ def ByIssuerId():
+ # ! [ByIssuerId]
+ contract = Contract()
+ contract.issuerId = "e1453318"
+ # ! [ByIssuerId]
+ return contract
+
+ @staticmethod
+ def FundContract():
+ # ! [fundcontract]
+ contract = Contract()
+ contract.symbol = "I406801954"
+ contract.secType = "FUND"
+ contract.exchange = "ALLFUNDS"
+ contract.currency = "USD"
+ # ! [fundcontract]
+ return contract
+
+ @staticmethod
+ def OptForecastx():
+ # ! [optforecastxcontract]
+ contract = Contract()
+ contract.symbol = "CPIY"
+ contract.secType = "OPT"
+ contract.lastTradeDateOrContractMonth = "202612"
+ contract.exchange = "FORECASTX"
+ contract.currency = "USD"
+ # ! [optforecastxcontract]
+ return contract
+
+ @staticmethod
+ def OptForecastxZeroStrike():
+ # ! [optforecastxcontract]
+ contract = Contract()
+ contract.symbol = "CPIY"
+ contract.secType = "OPT"
+ contract.lastTradeDateOrContractMonth = "202612"
+ contract.strike = 0
+ contract.right = "C"
+ contract.exchange = "FORECASTX"
+ contract.currency = "USD"
+ # ! [optforecastxcontract]
+ return contract
+
+ @staticmethod
+ def OptForecastxByConId():
+ # ! [optforecastxbyconid]
+ contract = Contract()
+ contract.conId = 789013783
+ contract.exchange = "FORECASTX"
+ # ! [optforecastxbyconid]
+ return contract
+
+def Test():
+ from ibapi.utils import ExerciseStaticMethods
+ ExerciseStaticMethods(ContractSamples)
+
+
+if "__main__" == __name__:
+ Test()
+
diff --git a/packages/ibkr/ref/samples/Python/Testbed/FaAllocationSamples.py b/packages/ibkr/ref/samples/Python/Testbed/FaAllocationSamples.py
new file mode 100644
index 00000000..2c9e34a6
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/FaAllocationSamples.py
@@ -0,0 +1,138 @@
+"""
+Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.object_implem import Object
+
+
+class FaAllocationSamples(Object):
+ #! [faupdatedgroup]
+ FaUpdatedGroup = "".join(("" ,
+ "" ,
+ "" ,
+ "MyTestProfile1" ,
+ "ContractsOrShares" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "100.0" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "200.0" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "MyTestProfile2" ,
+ "Ratio" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "1.0" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "2.0" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "MyTestProfile3" ,
+ "Percent" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "60.0" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "40.0" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "MyTestProfile4" ,
+ "MonetaryAmount" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "1000.0" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "2000.0" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "Group_1" ,
+ "NetLiq" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "MyTestGroup1" ,
+ "AvailableEquity" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "MyTestGroup2" ,
+ "NetLiq" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "MyTestGroup3" ,
+ "Equal" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "" ,
+ "" ,
+ "" ,
+ "" ,
+ "Group_2" ,
+ "AvailableEquity" ,
+ "" ,
+ "" ,
+ "DU6202167" ,
+ "" ,
+ "" ,
+ "DU6202168" ,
+ "" ,
+ "" ,
+ "" ,
+ ""))
+ #! [faupdatedgroup]
+
+def Test():
+ print(FaAllocationSamples.FaUpdatedGroup)
+
+if "__main__" == __name__:
+ Test()
+
+
diff --git a/packages/ibkr/ref/samples/Python/Testbed/OrderSamples.py b/packages/ibkr/ref/samples/Python/Testbed/OrderSamples.py
new file mode 100644
index 00000000..b61307f2
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/OrderSamples.py
@@ -0,0 +1,1271 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+from ibapi.order import (OrderComboLeg, Order, COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID)
+from ibapi.common import * # @UnusedWildImport
+from ibapi.tag_value import TagValue
+from ibapi import order_condition
+from ibapi.order_condition import * # @UnusedWildImport
+from ibapi.order_cancel import OrderCancel
+from decimal import Decimal
+
+
+class OrderSamples:
+
+ """
+ #/ An auction order is entered into the electronic trading system during the pre-market opening period for execution at the
+ #/ Calculated Opening Price (COP). If your order is not filled on the open, the order is re-submitted as a limit order with
+ #/ the limit price set to the COP or the best bid/ask after the market opens.
+ #/ Products: FUT, STK
+ """
+ @staticmethod
+ def AtAuction(action:str, quantity:Decimal, price:float):
+ #! [auction]
+ order = Order()
+ order.action = action
+ order.tif = "AUC"
+ order.orderType = "MTL"
+ order.totalQuantity = quantity
+ order.lmtPrice = price
+ #! [auction]
+ return order
+
+ """
+ #/ A Discretionary order is a limit order submitted with a hidden, specified 'discretionary' amount off the limit price which
+ #/ may be used to increase the price range over which the limit order is eligible to execute. The market sees only the limit price.
+ #/ Products: STK
+ """
+ @staticmethod
+ def Discretionary(action:str, quantity:Decimal, price:float, discretionaryAmount:float):
+
+ #! [discretionary]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = price
+ order.discretionaryAmt = discretionaryAmount
+ #! [discretionary]
+ return order
+
+
+ """
+ #/ A Market order is an order to buy or sell at the market bid or offer price. A market order may increase the likelihood of a fill
+ #/ and the speed of execution, but unlike the Limit order a Market order provides no price protection and may fill at a price far
+ #/ lower/higher than the current displayed bid/ask.
+ #/ Products: BOND, CFD, EFP, CASH, FUND, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def MarketOrder(action:str, quantity:Decimal):
+
+ #! [market]
+ order = Order()
+ order.action = action
+ order.orderType = "MKT"
+ order.totalQuantity = quantity
+ #! [market]
+ return order
+
+
+ """
+ #/ A Market if Touched (MIT) is an order to buy (or sell) a contract below (or above) the market. Its purpose is to take advantage
+ #/ of sudden or unexpected changes in share or other prices and provides investors with a trigger price to set an order in motion.
+ #/ Investors may be waiting for excessive strength (or weakness) to cease, which might be represented by a specific price point.
+ #/ MIT orders can be used to determine whether or not to enter the market once a specific price level has been achieved. This order
+ #/ is held in the system until the trigger price is touched, and is then submitted as a market order. An MIT order is similar to a
+ #/ stop order, except that an MIT sell order is placed above the current market price, and a stop sell order is placed below
+ #/ Products: BOND, CFD, CASH, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def MarketIfTouched(action:str, quantity:Decimal, price:float):
+
+ #! [market_if_touched]
+ order = Order()
+ order.action = action
+ order.orderType = "MIT"
+ order.totalQuantity = quantity
+ order.auxPrice = price
+ #! [market_if_touched]
+ return order
+
+
+ """
+ #/ A Market-on-Close (MOC) order is a market order that is submitted to execute as close to the closing price as possible.
+ #/ Products: CFD, FUT, STK, WAR
+ """
+ @staticmethod
+ def MarketOnClose(action:str, quantity:Decimal):
+
+ #! [market_on_close]
+ order = Order()
+ order.action = action
+ order.orderType = "MOC"
+ order.totalQuantity = quantity
+ #! [market_on_close]
+ return order
+
+
+ """
+ #/ A Market-on-Open (MOO) order combines a market order with the OPG time in force to create an order that is automatically
+ #/ submitted at the market's open and fills at the market price.
+ #/ Products: CFD, STK, OPT, WAR
+ """
+ @staticmethod
+ def MarketOnOpen(action:str, quantity:Decimal):
+
+ #! [market_on_open]
+ order = Order()
+ order.action = action
+ order.orderType = "MKT"
+ order.totalQuantity = quantity
+ order.tif = "OPG"
+ #! [market_on_open]
+ return order
+
+
+ """
+ #/ ISE MidpoMatch:int (MPM) orders always execute at the midpoof:the:int NBBO. You can submit market and limit orders direct-routed
+ #/ to ISE for MPM execution. Market orders execute at the midpowhenever:an:int eligible contra-order is available. Limit orders
+ #/ execute only when the midpoprice:is:int better than the limit price. Standard MPM orders are completely anonymous.
+ #/ Products: STK
+ """
+ @staticmethod
+ def MidpointMatch(action:str, quantity:Decimal):
+
+ #! [midpoint_match]
+ order = Order()
+ order.action = action
+ order.orderType = "MKT"
+ order.totalQuantity = quantity
+ #! [midpoint_match]
+ return order
+
+
+ """
+ #/ A Midprice order is designed to split the difference between the bid and ask prices, and fill at the current midpoint of
+ #/ the NBBO or better. Set an optional price cap to define the highest price (for a buy order) or the lowest price (for a sell
+ #/ order) you are willing to accept. Requires TWS 975+. Smart-routing to US stocks only.
+ """
+ @staticmethod
+ def Midprice(action:str, quantity:Decimal, priceCap:float):
+
+ #! [midprice]
+ order = Order()
+ order.action = action
+ order.orderType = "MIDPRICE"
+ order.totalQuantity = quantity
+ order.lmtPrice = priceCap # optional
+ #! [midprice]
+ return order
+
+ """
+ #/ A pegged-to-market order is designed to maintain a purchase price relative to the national best offer (NBO) or a sale price
+ #/ relative to the national best bid (NBB). Depending on the width of the quote, this order may be passive or aggressive.
+ #/ The trader creates the order by entering a limit price which defines the worst limit price that they are willing to accept.
+ #/ Next, the trader enters an offset amount which computes the active limit price as follows:
+ #/ Sell order price = Bid price + offset amount
+ #/ Buy order price = Ask price - offset amount
+ #/ Products: STK
+ """
+ @staticmethod
+ def PeggedToMarket(action:str, quantity:Decimal, marketOffset:float):
+
+ #! [pegged_market]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG MKT"
+ order.totalQuantity = quantity
+ order.auxPrice = marketOffset#Offset price
+ #! [pegged_market]
+ return order
+
+
+ """
+ #/ A Pegged to Stock order continually adjusts the option order price by the product of a signed user-define delta and the change of
+ #/ the option's underlying stock price. The delta is entered as an absolute and assumed to be positive for calls and negative for puts.
+ #/ A buy or sell call order price is determined by adding the delta times a change in an underlying stock price to a specified starting
+ #/ price for the call. To determine the change in price, the stock reference price is subtracted from the current NBBO midpoint.
+ #/ The Stock Reference Price can be defined by the user, or defaults to the NBBO midpoat:the:int time of the order if no reference price
+ #/ is entered. You may also enter a high/low stock price range which cancels the order when reached. The delta times the change in stock
+ #/ price will be rounded to the nearest penny in favor of the order.
+ #/ Products: OPT
+ """
+ @staticmethod
+ def PeggedToStock(action:str, quantity:Decimal, delta:float, stockReferencePrice:float, startingPrice:float):
+
+ #! [pegged_stock]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG STK"
+ order.totalQuantity = quantity
+ order.delta = delta
+ order.stockRefPrice = stockReferencePrice
+ order.startingPrice = startingPrice
+ #! [pegged_stock]
+ return order
+
+
+ """
+ #/ Relative (a.k.a. Pegged-to-Primary) orders provide a means for traders to seek a more aggressive price than the National Best Bid
+ #/ and Offer (NBBO). By acting as liquidity providers, and placing more aggressive bids and offers than the current best bids and offers,
+ #/ traders increase their odds of filling their order. Quotes are automatically adjusted as the markets move, to remain aggressive.
+ #/ For a buy order, your bid is pegged to the NBB by a more aggressive offset, and if the NBB moves up, your bid will also move up.
+ #/ If the NBB moves down, there will be no adjustment because your bid will become even more aggressive and execute. For sales, your
+ #/ offer is pegged to the NBO by a more aggressive offset, and if the NBO moves down, your offer will also move down. If the NBO moves up,
+ #/ there will be no adjustment because your offer will become more aggressive and execute. In addition to the offset, you can define an
+ #/ absolute cap, which works like a limit price, and will prevent your order from being executed above or below a specified level.
+ #/ Stocks, Options and Futures - not available on paper trading
+ #/ Products: CFD, STK, OPT, FUT
+ """
+ @staticmethod
+ def RelativePeggedToPrimary(action:str, quantity:Decimal, priceCap:float,
+ offsetAmount:float):
+
+ #! [relative_pegged_primary]
+ order = Order()
+ order.action = action
+ order.orderType = "REL"
+ order.totalQuantity = quantity
+ order.lmtPrice = priceCap
+ order.auxPrice = offsetAmount
+ #! [relative_pegged_primary]
+ return order
+
+
+ """
+ #/ Sweep-to-fill orders are useful when a trader values speed of execution over price. A sweep-to-fill order identifies the best price
+ #/ and the exact quantity offered/available at that price, and transmits the corresponding portion of your order for immediate execution.
+ #/ Simultaneously it identifies the next best price and quantity offered/available, and submits the matching quantity of your order for
+ #/ immediate execution.
+ #/ Products: CFD, STK, WAR
+ """
+ @staticmethod
+ def SweepToFill(action:str, quantity:Decimal, price:float):
+
+ #! [sweep_to_fill]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = price
+ order.sweepToFill = True
+ #! [sweep_to_fill]
+ return order
+
+
+ """
+ #/ For option orders routed to the Boston Options Exchange (BOX) you may elect to participate in the BOX's price improvement auction in
+ #/ pennies. All BOX-directed price improvement orders are immediately sent from Interactive Brokers to the BOX order book, and when the
+ #/ terms allow, IB will evaluate it for inclusion in a price improvement auction based on price and volume priority. In the auction, your
+ #/ order will have priority over broker-dealer price improvement orders at the same price.
+ #/ An Auction Limit order at a specified price. Use of a limit order ensures that you will not receive an execution at a price less favorable
+ #/ than the limit price. Enter limit orders in penny increments with your auction improvement amount computed as the difference between your
+ #/ limit order price and the nearest listed increment.
+ #/ Products: OPT
+ #/ Supported Exchanges: BOX
+ """
+ @staticmethod
+ def AuctionLimit(action:str, quantity:Decimal, price:float,
+ auctionStrategy:int):
+
+ #! [auction_limit]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = price
+ order.auctionStrategy = auctionStrategy
+ #! [auction_limit]
+ return order
+
+
+ """
+ #/ For option orders routed to the Boston Options Exchange (BOX) you may elect to participate in the BOX's price improvement auction in pennies.
+ #/ All BOX-directed price improvement orders are immediately sent from Interactive Brokers to the BOX order book, and when the terms allow,
+ #/ IB will evaluate it for inclusion in a price improvement auction based on price and volume priority. In the auction, your order will have
+ #/ priority over broker-dealer price improvement orders at the same price.
+ #/ An Auction Pegged to Stock order adjusts the order price by the product of a signed delta (which is entered as an absolute and assumed to be
+ #/ positive for calls, negative for puts) and the change of the option's underlying stock price. A buy or sell call order price is determined
+ #/ by adding the delta times a change in an underlying stock price change to a specified starting price for the call. To determine the change
+ #/ in price, a stock reference price (NBBO midpoat:the:int time of the order is assumed if no reference price is entered) is subtracted from
+ #/ the current NBBO midpoint. A stock range may also be entered that cancels an order when reached. The delta times the change in stock price
+ #/ will be rounded to the nearest penny in favor of the order and will be used as your auction improvement amount.
+ #/ Products: OPT
+ #/ Supported Exchanges: BOX
+ """
+ @staticmethod
+ def AuctionPeggedToStock(action:str, quantity:Decimal, startingPrice:float,
+ delta:float):
+
+ #! [auction_pegged_stock]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG STK"
+ order.totalQuantity = quantity
+ order.delta = delta
+ order.startingPrice = startingPrice
+ #! [auction_pegged_stock]
+ return order
+
+
+ """
+ #/ For option orders routed to the Boston Options Exchange (BOX) you may elect to participate in the BOX's price improvement auction in pennies.
+ #/ All BOX-directed price improvement orders are immediately sent from Interactive Brokers to the BOX order book, and when the terms allow,
+ #/ IB will evaluate it for inclusion in a price improvement auction based on price and volume priority. In the auction, your order will have
+ #/ priority over broker-dealer price improvement orders at the same price.
+ #/ An Auction Relative order that adjusts the order price by the product of a signed delta (which is entered as an absolute and assumed to be
+ #/ positive for calls, negative for puts) and the change of the option's underlying stock price. A buy or sell call order price is determined
+ #/ by adding the delta times a change in an underlying stock price change to a specified starting price for the call. To determine the change
+ #/ in price, a stock reference price (NBBO midpoat:the:int time of the order is assumed if no reference price is entered) is subtracted from
+ #/ the current NBBO midpoint. A stock range may also be entered that cancels an order when reached. The delta times the change in stock price
+ #/ will be rounded to the nearest penny in favor of the order and will be used as your auction improvement amount.
+ #/ Products: OPT
+ #/ Supported Exchanges: BOX
+ """
+ @staticmethod
+ def AuctionRelative(action:str, quantity:Decimal, offset:float):
+
+ #! [auction_relative]
+ order = Order()
+ order.action = action
+ order.orderType = "REL"
+ order.totalQuantity = quantity
+ order.auxPrice = offset
+ #! [auction_relative]
+ return order
+
+
+ """
+ #/ The Block attribute is used for large volume option orders on ISE that consist of at least 50 contracts. To execute large-volume
+ #/ orders over time without moving the market, use the Accumulate/Distribute algorithm.
+ #/ Products: OPT
+ """
+ @staticmethod
+ def Block(action:str, quantity:Decimal, price:float):
+
+ # ! [block]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity#Large volumes!
+ order.lmtPrice = price
+ order.blockOrder = True
+ # ! [block]
+ return order
+
+
+ """
+ #/ A Box Top order executes as a market order at the current best price. If the order is only partially filled, the remainder is submitted as
+ #/ a limit order with the limit price equal to the price at which the filled portion of the order executed.
+ #/ Products: OPT
+ #/ Supported Exchanges: BOX
+ """
+ @staticmethod
+ def BoxTop(action:str, quantity:Decimal):
+
+ # ! [boxtop]
+ order = Order()
+ order.action = action
+ order.orderType = "BOX TOP"
+ order.totalQuantity = quantity
+ # ! [boxtop]
+ return order
+
+
+ """
+ #/ A Limit order is an order to buy or sell at a specified price or better. The Limit order ensures that if the order fills,
+ #/ it will not fill at a price less favorable than your limit price, but it does not guarantee a fill.
+ #/ Products: BOND, CFD, CASH, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def LimitOrder(action:str, quantity:Decimal, limitPrice:float):
+
+ # ! [limitorder]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ order.tif = "DAY"
+ # ! [limitorder]
+ return order
+
+ """
+ #/ Forex orders can be placed in demonination of second currency in pair using cashQty field
+ #/ Requires TWS or IBG 963+
+ #/ https://www.interactivebrokers.com/en/index.php?f=23876#963-02
+ """
+
+ @staticmethod
+ def LimitOrderWithCashQty(action:str, limitPrice:float, cashQty:float):
+
+ # ! [limitorderwithcashqty]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.lmtPrice = limitPrice
+ order.cashQty = cashQty
+ # ! [limitorderwithcashqty]
+ return order
+
+
+ """
+ #/ A Limit if Touched is an order to buy (or sell) a contract at a specified price or better, below (or above) the market. This order is
+ #/ held in the system until the trigger price is touched. An LIT order is similar to a stop limit order, except that an LIT sell order is
+ #/ placed above the current market price, and a stop limit sell order is placed below.
+ #/ Products: BOND, CFD, CASH, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def LimitIfTouched(action:str, quantity:Decimal, limitPrice:float,
+ triggerPrice:float):
+
+ # ! [limitiftouched]
+ order = Order()
+ order.action = action
+ order.orderType = "LIT"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ order.auxPrice = triggerPrice
+ # ! [limitiftouched]
+ return order
+
+
+ """
+ #/ A Limit-on-close (LOC) order will be submitted at the close and will execute if the closing price is at or better than the submitted
+ #/ limit price.
+ #/ Products: CFD, FUT, STK, WAR
+ """
+ @staticmethod
+ def LimitOnClose(action:str, quantity:Decimal, limitPrice:float):
+
+ # ! [limitonclose]
+ order = Order()
+ order.action = action
+ order.orderType = "LOC"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ # ! [limitonclose]
+ return order
+
+
+ """
+ #/ A Limit-on-Open (LOO) order combines a limit order with the OPG time in force to create an order that is submitted at the market's open,
+ #/ and that will only execute at the specified limit price or better. Orders are filled in accordance with specific exchange rules.
+ #/ Products: CFD, STK, OPT, WAR
+ """
+ @staticmethod
+ def LimitOnOpen(action:str, quantity:Decimal, limitPrice:float):
+
+ # ! [limitonopen]
+ order = Order()
+ order.action = action
+ order.tif = "OPG"
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ # ! [limitonopen]
+ return order
+
+
+ """
+ #/ Passive Relative orders provide a means for traders to seek a less aggressive price than the National Best Bid and Offer (NBBO) while
+ #/ keeping the order pegged to the best bid (for a buy) or ask (for a sell). The order price is automatically adjusted as the markets move
+ #/ to keep the order less aggressive. For a buy order, your order price is pegged to the NBB by a less aggressive offset, and if the NBB
+ #/ moves up, your bid will also move up. If the NBB moves down, there will be no adjustment because your bid will become aggressive and execute.
+ #/ For a sell order, your price is pegged to the NBO by a less aggressive offset, and if the NBO moves down, your offer will also move down.
+ #/ If the NBO moves up, there will be no adjustment because your offer will become aggressive and execute. In addition to the offset, you can
+ #/ define an absolute cap, which works like a limit price, and will prevent your order from being executed above or below a specified level.
+ #/ The Passive Relative order is similar to the Relative/Pegged-to-Primary order, except that the Passive relative subtracts the offset from
+ #/ the bid and the Relative adds the offset to the bid.
+ #/ Products: STK, WAR
+ """
+ @staticmethod
+ def PassiveRelative(action:str, quantity:Decimal, offset:float):
+
+ # ! [passive_relative]
+ order = Order()
+ order.action = action
+ order.orderType = "PASSV REL"
+ order.totalQuantity = quantity
+ order.auxPrice = offset
+ # ! [passive_relative]
+ return order
+
+
+ """
+ #/ A pegged-to-midpoorder:provides:int a means for traders to seek a price at the midpoof:the:int National Best Bid and Offer (NBBO).
+ #/ The price automatically adjusts to peg the midpoas:the:int markets move, to remain aggressive. For a buy order, your bid is pegged to
+ #/ the NBBO midpoand:the:int order price adjusts automatically to continue to peg the midpoif:the:int market moves. The price only adjusts
+ #/ to be more aggressive. If the market moves in the opposite direction, the order will execute.
+ #/ Products: STK
+ """
+ @staticmethod
+ def PeggedToMidpoint(action:str, quantity:Decimal, offset:float, limitPrice:float):
+
+ # ! [pegged_midpoint]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG MID"
+ order.totalQuantity = quantity
+ order.auxPrice = offset
+ order.lmtPrice = limitPrice
+ # ! [pegged_midpoint]
+ return order
+
+
+ """
+ #/ Bracket orders are designed to help limit your loss and lock in a profit by "bracketing" an order with two opposite-side orders.
+ #/ A BUY order is bracketed by a high-side sell limit order and a low-side sell stop order. A SELL order is bracketed by a high-side buy
+ #/ stop order and a low side buy limit order.
+ #/ Products: CFD, BAG, FOP, CASH, FUT, OPT, STK, WAR
+ """
+ #! [bracket]
+ @staticmethod
+ def BracketOrder(parentOrderId:int, action:str, quantity:Decimal,
+ limitPrice:float, takeProfitLimitPrice:float,
+ stopLossPrice:float):
+
+ #This will be our main or "parent" order
+ parent = Order()
+ parent.orderId = parentOrderId
+ parent.action = action
+ parent.orderType = "LMT"
+ parent.totalQuantity = quantity
+ parent.lmtPrice = limitPrice
+ #The parent and children orders will need this attribute set to False to prevent accidental executions.
+ #The LAST CHILD will have it set to True,
+ parent.transmit = False
+
+ takeProfit = Order()
+ takeProfit.orderId = parent.orderId + 1
+ takeProfit.action = "SELL" if action == "BUY" else "BUY"
+ takeProfit.orderType = "LMT"
+ takeProfit.totalQuantity = quantity
+ takeProfit.lmtPrice = takeProfitLimitPrice
+ takeProfit.parentId = parentOrderId
+ takeProfit.transmit = False
+
+ stopLoss = Order()
+ stopLoss.orderId = parent.orderId + 2
+ stopLoss.action = "SELL" if action == "BUY" else "BUY"
+ stopLoss.orderType = "STP"
+ #Stop trigger price
+ stopLoss.auxPrice = stopLossPrice
+ stopLoss.totalQuantity = quantity
+ stopLoss.parentId = parentOrderId
+ #In this case, the low side order will be the last child being sent. Therefore, it needs to set this attribute to True
+ #to activate all its predecessors
+ stopLoss.transmit = True
+
+ bracketOrder = [parent, takeProfit, stopLoss]
+ return bracketOrder
+
+ #! [bracket]
+
+ """
+ #/ Products:CFD, FUT, FOP, OPT, STK, WAR
+ #/ A Market-to-Limit (MTL) order is submitted as a market order to execute at the current best market price. If the order is only
+ #/ partially filled, the remainder of the order is canceled and re-submitted as a limit order with the limit price equal to the price
+ #/ at which the filled portion of the order executed.
+ """
+ @staticmethod
+ def MarketToLimit(action:str, quantity:Decimal):
+
+ # ! [markettolimit]
+ order = Order()
+ order.action = action
+ order.orderType = "MTL"
+ order.totalQuantity = quantity
+ # ! [markettolimit]
+ return order
+
+
+ """
+ #/ This order type is useful for futures traders using Globex. A Market with Protection order is a market order that will be cancelled and
+ #/ resubmitted as a limit order if the entire order does not immediately execute at the market price. The limit price is set by Globex to be
+ #/ close to the current market price, slightly higher for a sell order and lower for a buy order.
+ #/ Products: FUT, FOP
+ """
+ @staticmethod
+ def MarketWithProtection(action:str, quantity:Decimal):
+
+ # ! [marketwithprotection]
+ order = Order()
+ order.action = action
+ order.orderType = "MKT PRT"
+ order.totalQuantity = quantity
+ # ! [marketwithprotection]
+ return order
+
+
+ """
+ #/ A Stop order is an instruction to submit a buy or sell market order if and when the user-specified stop trigger price is attained or
+ #/ penetrated. A Stop order is not guaranteed a specific execution price and may execute significantly away from its stop price. A Sell
+ #/ Stop order is always placed below the current market price and is typically used to limit a loss or protect a profit on a long stock
+ #/ position. A Buy Stop order is always placed above the current market price. It is typically used to limit a loss or help protect a
+ #/ profit on a short sale.
+ #/ Products: CFD, BAG, CASH, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def Stop(action:str, quantity:Decimal, stopPrice:float):
+
+ # ! [stop]
+ order = Order()
+ order.action = action
+ order.orderType = "STP"
+ order.auxPrice = stopPrice
+ order.totalQuantity = quantity
+ # ! [stop]
+ return order
+
+
+ """
+ #/ A Stop-Limit order is an instruction to submit a buy or sell limit order when the user-specified stop trigger price is attained or
+ #/ penetrated. The order has two basic components: the stop price and the limit price. When a trade has occurred at or through the stop
+ #/ price, the order becomes executable and enters the market as a limit order, which is an order to buy or sell at a specified price or better.
+ #/ Products: CFD, CASH, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def StopLimit(action:str, quantity:Decimal, limitPrice:float, stopPrice:float):
+
+ # ! [stoplimit]
+ order = Order()
+ order.action = action
+ order.orderType = "STP LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ order.auxPrice = stopPrice
+ # ! [stoplimit]
+ return order
+
+
+ """
+ #/ A Stop with Protection order combines the functionality of a stop limit order with a market with protection order. The order is set
+ #/ to trigger at a specified stop price. When the stop price is penetrated, the order is triggered as a market with protection order,
+ #/ which means that it will fill within a specified protected price range equal to the trigger price +/- the exchange-defined protection
+ #/ porange:int. Any portion of the order that does not fill within this protected range is submitted as a limit order at the exchange-defined
+ #/ trigger price +/- the protection points.
+ #/ Products: FUT
+ """
+ @staticmethod
+ def StopWithProtection(action:str, quantity:Decimal, stopPrice:float):
+
+ # ! [stopwithprotection]
+ order = Order()
+ order.totalQuantity = quantity
+ order.action = action
+ order.orderType = "STP PRT"
+ order.auxPrice = stopPrice
+ # ! [stopwithprotection]
+ return order
+
+
+ """
+ #/ A sell trailing stop order sets the stop price at a fixed amount below the market price with an attached "trailing" amount. As the
+ #/ market price rises, the stop price rises by the trail amount, but if the stock price falls, the stop loss price doesn't change,
+ #/ and a market order is submitted when the stop price is hit. This technique is designed to allow an investor to specify a limit on the
+ #/ maximum possible loss, without setting a limit on the maximum possible gain. "Buy" trailing stop orders are the mirror image of sell
+ #/ trailing stop orders, and are most appropriate for use in falling markets.
+ #/ Products: CFD, CASH, FOP, FUT, OPT, STK, WAR
+ """
+ @staticmethod
+ def TrailingStop(action:str, quantity:Decimal, trailingPercent:float,
+ trailStopPrice:float):
+
+ # ! [trailingstop]
+ order = Order()
+ order.action = action
+ order.orderType = "TRAIL"
+ order.totalQuantity = quantity
+ order.trailingPercent = trailingPercent
+ order.trailStopPrice = trailStopPrice
+ # ! [trailingstop]
+ return order
+
+
+ """
+ #/ A trailing stop limit order is designed to allow an investor to specify a limit on the maximum possible loss, without setting a limit
+ #/ on the maximum possible gain. A SELL trailing stop limit moves with the market price, and continually recalculates the stop trigger
+ #/ price at a fixed amount below the market price, based on the user-defined "trailing" amount. The limit order price is also continually
+ #/ recalculated based on the limit offset. As the market price rises, both the stop price and the limit price rise by the trail amount and
+ #/ limit offset respectively, but if the stock price falls, the stop price remains unchanged, and when the stop price is hit a limit order
+ #/ is submitted at the last calculated limit price. A "Buy" trailing stop limit order is the mirror image of a sell trailing stop limit,
+ #/ and is generally used in falling markets.
+ #/ Products: BOND, CFD, CASH, FUT, FOP, OPT, STK, WAR
+ """
+ @staticmethod
+ def TrailingStopLimit(action:str, quantity:Decimal, lmtPriceOffset:float,
+ trailingAmount:float, trailStopPrice:float):
+
+ # ! [trailingstoplimit]
+ order = Order()
+ order.action = action
+ order.orderType = "TRAIL LIMIT"
+ order.totalQuantity = quantity
+ order.trailStopPrice = trailStopPrice
+ order.lmtPriceOffset = lmtPriceOffset
+ order.auxPrice = trailingAmount
+ # ! [trailingstoplimit]
+ return order
+
+
+ """
+ #/ Create combination orders that include options, stock and futures legs (stock legs can be included if the order is routed
+ #/ through SmartRouting). Although a combination/spread order is constructed of separate legs, it is executed as a single transaction
+ #/ if it is routed directly to an exchange. For combination orders that are SmartRouted, each leg may be executed separately to ensure
+ #/ best execution.
+ #/ Products: OPT, STK, FUT
+ """
+ @staticmethod
+ def ComboLimitOrder(action:str, quantity:Decimal, limitPrice:float,
+ nonGuaranteed:bool):
+
+ # ! [combolimit]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ if nonGuaranteed:
+
+ order.smartComboRoutingParams = []
+ order.smartComboRoutingParams.append(TagValue("NonGuaranteed", "1"))
+
+ # ! [combolimit]
+ return order
+
+
+ """
+ #/ Create combination orders that include options, stock and futures legs (stock legs can be included if the order is routed
+ #/ through SmartRouting). Although a combination/spread order is constructed of separate legs, it is executed as a single transaction
+ #/ if it is routed directly to an exchange. For combination orders that are SmartRouted, each leg may be executed separately to ensure
+ #/ best execution.
+ #/ Products: OPT, STK, FUT
+ """
+ @staticmethod
+ def ComboMarketOrder(action:str, quantity:Decimal, nonGuaranteed:bool):
+
+ # ! [combomarket]
+ order = Order()
+ order.action = action
+ order.orderType = "MKT"
+ order.totalQuantity = quantity
+ if nonGuaranteed:
+
+ order.smartComboRoutingParams = []
+ order.smartComboRoutingParams.append(TagValue("NonGuaranteed", "1"))
+
+ # ! [combomarket]
+ return order
+
+
+ """
+ #/ Create combination orders that include options, stock and futures legs (stock legs can be included if the order is routed
+ #/ through SmartRouting). Although a combination/spread order is constructed of separate legs, it is executed as a single transaction
+ #/ if it is routed directly to an exchange. For combination orders that are SmartRouted, each leg may be executed separately to ensure
+ #/ best execution.
+ #/ Products: OPT, STK, FUT
+ """
+ @staticmethod
+ def LimitOrderForComboWithLegPrices(action:str, quantity:Decimal,
+ legPrices:list, nonGuaranteed:bool):
+
+ # ! [limitordercombolegprices]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.totalQuantity = quantity
+ order.orderComboLegs = []
+ for price in legPrices:
+
+ comboLeg = OrderComboLeg()
+ comboLeg.price = price
+ order.orderComboLegs.append(comboLeg)
+
+ if nonGuaranteed:
+ order.smartComboRoutingParams = []
+ order.smartComboRoutingParams.append(TagValue("NonGuaranteed", "1"))
+
+ # ! [limitordercombolegprices]
+ return order
+
+
+ """
+ #/ Create combination orders that include options, stock and futures legs (stock legs can be included if the order is routed
+ #/ through SmartRouting). Although a combination/spread order is constructed of separate legs, it is executed as a single transaction
+ #/ if it is routed directly to an exchange. For combination orders that are SmartRouted, each leg may be executed separately to ensure
+ #/ best execution.
+ #/ Products: OPT, STK, FUT
+ """
+ @staticmethod
+ def RelativeLimitCombo(action:str, quantity:Decimal, limitPrice:float,
+ nonGuaranteed:bool):
+
+ # ! [relativelimitcombo]
+ order = Order()
+ order.action = action
+ order.totalQuantity = quantity
+ order.orderType = "REL + LMT"
+ order.lmtPrice = limitPrice
+ if nonGuaranteed:
+
+ order.smartComboRoutingParams = []
+ order.smartComboRoutingParams.append(TagValue("NonGuaranteed", "1"))
+
+ # ! [relativelimitcombo]
+ return order
+
+
+ """
+ #/ Create combination orders that include options, stock and futures legs (stock legs can be included if the order is routed
+ #/ through SmartRouting). Although a combination/spread order is constructed of separate legs, it is executed as a single transaction
+ #/ if it is routed directly to an exchange. For combination orders that are SmartRouted, each leg may be executed separately to ensure
+ #/ best execution.
+ #/ Products: OPT, STK, FUT
+ """
+ @staticmethod
+ def RelativeMarketCombo(action:str, quantity:Decimal, nonGuaranteed:bool):
+
+ # ! [relativemarketcombo]
+ order = Order()
+ order.action = action
+ order.totalQuantity = quantity
+ order.orderType = "REL + MKT"
+ if nonGuaranteed:
+
+ order.smartComboRoutingParams = []
+ order.smartComboRoutingParams.append(TagValue("NonGuaranteed", "1"))
+
+ # ! [relativemarketcombo]
+ return order
+
+
+ """
+ #/ One-Cancels All (OCA) order type allows an investor to place multiple and possibly unrelated orders assigned to a group. The aim is
+ #/ to complete just one of the orders, which in turn will cause TWS to cancel the remaining orders. The investor may submit several
+ #/ orders aimed at taking advantage of the most desirable price within the group. Completion of one piece of the group order causes
+ #/ cancellation of the remaining group orders while partial completion causes the group to rebalance. An investor might desire to sell
+ #/ 1000 shares of only ONE of three positions held above prevailing market prices. The OCA order group allows the investor to enter prices
+ #/ at specified target levels and if one is completed, the other two will automatically cancel. Alternatively, an investor may wish to take
+ #/ a LONG position in eMini S&P stock index futures in a falling market or else SELL US treasury futures at a more favorable price.
+ #/ Grouping the two orders using an OCA order type offers the investor two chance to enter a similar position, while only running the risk
+ #/ of taking on a single position.
+ #/ Products: BOND, CASH, FUT, FOP, STK, OPT, WAR
+ """
+ # ! [oca]
+ @staticmethod
+ def OneCancelsAll(ocaGroup:str, ocaOrders:ListOfOrder, ocaType:int):
+
+ for o in ocaOrders:
+
+ o.ocaGroup = ocaGroup
+ o.ocaType = ocaType
+
+ return ocaOrders
+
+ # ! [oca]
+
+ """
+ #/ Specific to US options, investors are able to create and enter Volatility-type orders for options and combinations rather than price orders.
+ #/ Option traders may wish to trade and position for movements in the price of the option determined by its implied volatility. Because
+ #/ implied volatility is a key determinant of the premium on an option, traders position in specific contract months in an effort to take
+ #/ advantage of perceived changes in implied volatility arising before, during or after earnings or when company specific or broad market
+ #/ volatility is predicted to change. In order to create a Volatility order, clients must first create a Volatility Trader page from the
+ #/ Trading Tools menu and as they enter option contracts, premiums will display in percentage terms rather than premium. The buy/sell process
+ #/ is the same as for regular orders priced in premium terms except that the client can limit the volatility level they are willing to pay or
+ #/ receive.
+ #/ Products: FOP, OPT
+ """
+ @staticmethod
+ def Volatility(action:str, quantity:Decimal, volatilityPercent:float,
+ volatilityType:int):
+
+ # ! [volatility]
+ order = Order()
+ order.action = action
+ order.orderType = "VOL"
+ order.totalQuantity = quantity
+ order.volatility = volatilityPercent#Expressed in percentage (40%)
+ order.volatilityType = volatilityType# 1=daily, 2=annual
+ # ! [volatility]
+ return order
+
+
+ #! [fhedge]
+ @staticmethod
+ def MarketFHedge(parentOrderId:int, action:str):
+
+ #FX Hedge orders can only have a quantity of 0
+ order = OrderSamples.MarketOrder(action, 0)
+ order.parentId = parentOrderId
+ order.hedgeType = "F"
+ return order
+
+ #! [fhedge]
+
+ @staticmethod
+ def PeggedToBenchmark(action:str, quantity:Decimal, startingPrice:float,
+ peggedChangeAmountDecrease:bool,
+ peggedChangeAmount:float,
+ referenceChangeAmount:float, referenceConId:int,
+ referenceExchange:str, stockReferencePrice:float,
+ referenceContractLowerRange:float,
+ referenceContractUpperRange:float):
+
+ #! [pegged_benchmark]
+ order = Order()
+ order.orderType = "PEG BENCH"
+ #BUY or SELL
+ order.action = action
+ order.totalQuantity = quantity
+ #Beginning with price...
+ order.startingPrice = startingPrice
+ #increase/decrease price..
+ order.isPeggedChangeAmountDecrease = peggedChangeAmountDecrease
+ #by... (and likewise for price moving in opposite direction)
+ order.peggedChangeAmount = peggedChangeAmount
+ #whenever there is a price change of...
+ order.referenceChangeAmount = referenceChangeAmount
+ #in the reference contract...
+ order.referenceContractId = referenceConId
+ #being traded at...
+ order.referenceExchange = referenceExchange
+ #starting reference price is...
+ order.stockRefPrice = stockReferencePrice
+ #Keep order active as long as reference contract trades between...
+ order.stockRangeLower = referenceContractLowerRange
+ #and...
+ order.stockRangeUpper = referenceContractUpperRange
+ #! [pegged_benchmark]
+ return order
+
+
+
+ @staticmethod
+ def AttachAdjustableToStop(parent:Order , attachedOrderStopPrice:float,
+ triggerPrice:float, adjustStopPrice:float):
+
+ #! [adjustable_stop]
+ # Attached order is a conventional STP order in opposite direction
+ order = OrderSamples.Stop("SELL" if parent.action == "BUY" else "BUY",
+ parent.totalQuantity, attachedOrderStopPrice)
+ order.parentId = parent.orderId
+ #When trigger price is penetrated
+ order.triggerPrice = triggerPrice
+ #The parent order will be turned into a STP order
+ order.adjustedOrderType = "STP"
+ #With the given STP price
+ order.adjustedStopPrice = adjustStopPrice
+ #! [adjustable_stop]
+ return order
+
+
+ @staticmethod
+ def AttachAdjustableToStopLimit(parent:Order, attachedOrderStopPrice:float,
+ triggerPrice:float, adjustedStopPrice:float,
+ adjustedStopLimitPrice:float):
+
+ #! [adjustable_stop_limit]
+ #Attached order is a conventional STP order
+ order = OrderSamples.Stop("SELL" if parent.action == "BUY" else "BUY",
+ parent.totalQuantity, attachedOrderStopPrice)
+ order.parentId = parent.orderId
+ #When trigger price is penetrated
+ order.triggerPrice = triggerPrice
+ #The parent order will be turned into a STP LMT order
+ order.adjustedOrderType = "STP LMT"
+ #With the given stop price
+ order.adjustedStopPrice = adjustedStopPrice
+ #And the given limit price
+ order.adjustedStopLimitPrice = adjustedStopLimitPrice
+ #! [adjustable_stop_limit]
+ return order
+
+
+ @staticmethod
+ def AttachAdjustableToTrail(parent:Order, attachedOrderStopPrice:float,
+ triggerPrice:float, adjustedStopPrice:float,
+ adjustedTrailAmount:float, trailUnit:int):
+ #! [adjustable_trail]
+ #Attached order is a conventional STP order
+ order = OrderSamples.Stop("SELL" if parent.action == "BUY" else "BUY",
+ parent.totalQuantity, attachedOrderStopPrice)
+ order.parentId = parent.orderId
+ #When trigger price is penetrated
+ order.triggerPrice = triggerPrice
+ #The parent order will be turned into a TRAIL order
+ order.adjustedOrderType = "TRAIL"
+ #With a stop price of...
+ order.adjustedStopPrice = adjustedStopPrice
+ #trailing by and amount (0) or a percent (100)...
+ order.adjustableTrailingUnit = trailUnit
+ #of...
+ order.adjustedTrailingAmount = adjustedTrailAmount
+ #! [adjustable_trail]
+ return order
+
+
+ @staticmethod
+ def PriceCondition(triggerMethod:int, conId:int, exchange:str, price:float,
+ isMore:bool, isConjunction:bool):
+
+ #! [price_condition]
+ #Conditions have to be created via the OrderCondition.create
+ priceCondition = order_condition.Create(OrderCondition.Price)
+ #When this contract...
+ priceCondition.conId = conId
+ #traded on this exchange
+ priceCondition.exchange = exchange
+ #has a price above/below
+ priceCondition.isMore = isMore
+ priceCondition.triggerMethod = triggerMethod
+ #this quantity
+ priceCondition.price = price
+ #AND | OR next condition (will be ignored if no more conditions are added)
+ priceCondition.isConjunctionConnection = isConjunction
+ #! [price_condition]
+ return priceCondition
+
+
+ @staticmethod
+ def ExecutionCondition(symbol:str, secType:str, exchange:str,
+ isConjunction:bool):
+
+ #! [execution_condition]
+ execCondition = order_condition.Create(OrderCondition.Execution)
+ #When an execution on symbol
+ execCondition.symbol = symbol
+ #at exchange
+ execCondition.exchange = exchange
+ #for this secType
+ execCondition.secType = secType
+ #AND | OR next condition (will be ignored if no more conditions are added)
+ execCondition.isConjunctionConnection = isConjunction
+ #! [execution_condition]
+ return execCondition
+
+
+ @staticmethod
+ def MarginCondition(percent:int, isMore:bool, isConjunction:bool):
+
+ #! [margin_condition]
+ marginCondition = order_condition.Create(OrderCondition.Margin)
+ #If margin is above/below
+ marginCondition.isMore = isMore
+ #given percent
+ marginCondition.percent = percent
+ #AND | OR next condition (will be ignored if no more conditions are added)
+ marginCondition.isConjunctionConnection = isConjunction
+ #! [margin_condition]
+ return marginCondition
+
+
+ @staticmethod
+ def PercentageChangeCondition(pctChange:float, conId:int, exchange:str,
+ isMore:bool, isConjunction:bool):
+
+ #! [percentage_condition]
+ pctChangeCondition = order_condition.Create(OrderCondition.PercentChange)
+ #If there is a price percent change measured against last close price above or below...
+ pctChangeCondition.isMore = isMore
+ #this amount...
+ pctChangeCondition.changePercent = pctChange
+ #on this contract
+ pctChangeCondition.conId = conId
+ #when traded on this exchange...
+ pctChangeCondition.exchange = exchange
+ #AND | OR next condition (will be ignored if no more conditions are added)
+ pctChangeCondition.isConjunctionConnection = isConjunction
+ #! [percentage_condition]
+ return pctChangeCondition
+
+
+ @staticmethod
+ def TimeCondition(time:str, isMore:bool, isConjunction:bool):
+
+ #! [time_condition]
+ timeCondition = order_condition.Create(OrderCondition.Time)
+ #Before or after...
+ timeCondition.isMore = isMore
+ #this time..
+ timeCondition.time = time
+ #AND | OR next condition (will be ignored if no more conditions are added)
+ timeCondition.isConjunctionConnection = isConjunction
+ #! [time_condition]
+ return timeCondition
+
+
+ @staticmethod
+ def VolumeCondition(conId:int, exchange:str, isMore:bool, volume:int,
+ isConjunction:bool):
+
+ #! [volume_condition]
+ volCond = order_condition.Create(OrderCondition.Volume)
+ #Whenever contract...
+ volCond.conId = conId
+ #When traded at
+ volCond.exchange = exchange
+ #reaches a volume higher/lower
+ volCond.isMore = isMore
+ #than this...
+ volCond.volume = volume
+ #AND | OR next condition (will be ignored if no more conditions are added)
+ volCond.isConjunctionConnection = isConjunction
+ #! [volume_condition]
+ return volCond
+
+ @staticmethod
+ def LimitIBKRATS(action:str, quantity:Decimal, limitPrice:float):
+
+ # ! [limit_ibkrats]
+ order = Order()
+ order.action = action
+ order.orderType = "LMT"
+ order.lmtPrice = limitPrice
+ order.totalQuantity = quantity
+ order.notHeld = True
+ # ! [limit_ibkrats]
+ return order
+
+ @staticmethod
+ def LimitOrderWithManualOrderTime(action:str, quantity:Decimal, limitPrice:float, manualOrderTime:str):
+
+ # ! [limit_order_with_manual_order_time]
+ order = OrderSamples.LimitOrder(action, quantity, limitPrice)
+ order.manualOrderTime = manualOrderTime
+ # ! [limit_order_with_manual_order_time]
+ return order
+
+ @staticmethod
+ def PegBestUpToMidOrder(action:str, quantity:Decimal, limitPrice:float, minTradeQty:int, minCompeteSize:int, midOffsetAtWhole:float, midOffsetAtHalf:float):
+
+ # ! [peg_best_up_to_mid_order]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG BEST"
+ order.lmtPrice = limitPrice
+ order.totalQuantity = quantity
+ order.notHeld = True
+ order.minTradeQty = minTradeQty
+ order.minCompeteSize = minCompeteSize
+ order.competeAgainstBestOffset = COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID
+ order.midOffsetAtWhole = midOffsetAtWhole
+ order.midOffsetAtHalf = midOffsetAtHalf
+ # ! [peg_best_up_to_mid_order]
+ return order
+
+ @staticmethod
+ def PegBestOrder(action:str, quantity:Decimal, limitPrice:float, minTradeQty:int, minCompeteSize:int, competeAgainstBestOffset:float):
+
+ # ! [peg_best_order]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG BEST"
+ order.lmtPrice = limitPrice
+ order.totalQuantity = quantity
+ order.notHeld = True
+ order.minTradeQty = minTradeQty
+ order.minCompeteSize = minCompeteSize
+ order.competeAgainstBestOffset = competeAgainstBestOffset
+ # ! [peg_best_order]
+ return order
+
+ @staticmethod
+ def PegMidOrder(action:str, quantity:Decimal, limitPrice:float, minTradeQty:int, midOffsetAtWhole:float, midOffsetAtHalf:float):
+
+ # ! [peg_mid_order]
+ order = Order()
+ order.action = action
+ order.orderType = "PEG MID"
+ order.lmtPrice = limitPrice
+ order.totalQuantity = quantity
+ order.notHeld = True
+ order.minTradeQty = minTradeQty
+ order.midOffsetAtWhole = midOffsetAtWhole
+ order.midOffsetAtHalf = midOffsetAtHalf
+ # ! [peg_mid_order]
+ return order
+
+ @staticmethod
+ def LimitOrderWithCustomerAccount(action:str, quantity:Decimal, limitPrice:float, customerAccount:str):
+
+ # ! [limit_order_with_customer_account]
+ order = OrderSamples.LimitOrder(action, quantity, limitPrice)
+ order.customerAccount = customerAccount
+ # ! [limit_order_with_customer_account]
+ return order
+
+ @staticmethod
+ def LimitOrderWithIncludeOvernight(action:str, quantity:Decimal, limitPrice:float):
+
+ # ! [limit_order_with_include_overnight]
+ order = OrderSamples.LimitOrder(action, quantity, limitPrice)
+ order.includeOvernight = True
+ # ! [limit_order_with_include_overnight]
+ return order
+
+ @staticmethod
+ def CancelOrderEmpty():
+ # ! [cancel_order_empty]
+ orderCancel = OrderCancel()
+ # ! [cancel_order_empty]
+ return orderCancel
+
+ @staticmethod
+ def CancelOrderWithManualTime(manualOrderCancelTime: str):
+ # ! [cancel_order_with_manual_time]
+ orderCancel = OrderCancel()
+ orderCancel.manualOrderCancelTime = manualOrderCancelTime
+ # ! [cancel_order_with_manual_time]
+ return orderCancel
+
+ @staticmethod
+ def LimitOrderWithCmeTaggingFields(action: str, quantity: Decimal, limitPrice: float, extOperator: str, manualOrderIndicator: int):
+ # ! [limit_order_with_cme_tagging_fields]
+ order = OrderSamples.LimitOrder(action, quantity, limitPrice)
+ order.extOperator = extOperator
+ order.manualOrderIndicator = manualOrderIndicator
+ # ! [limit_order_with_cme_tagging_fields]
+ return order
+
+ @staticmethod
+ def OrderCancelWithCmeTaggingFields(extOperator: str, manualOrderIndicator: int):
+ # ! [order_cancel_with_cme_tagging_fields]
+ orderCancel = OrderCancel()
+ orderCancel.extOperator = extOperator
+ orderCancel.manualOrderIndicator = manualOrderIndicator
+ # ! [order_cancel_with_cme_tagging_fields]
+ return orderCancel
+
+ @staticmethod
+ def LimitOnCloseOrderWithImbalanceOnly(action:str, quantity:Decimal, limitPrice:float):
+ # ! [limit_on_close_order_with_imbalance_only]
+ order = Order()
+ order.action = action
+ order.orderType = "LOC"
+ order.totalQuantity = quantity
+ order.lmtPrice = limitPrice
+ order.imbalanceOnly = True
+ # ! [limit_on_close_order_with_imbalance_only]
+ return order
+
+ @staticmethod
+ def LimitOrderWithStopLossAndProfitTaker(action:str, quantity:Decimal, limitPrice:float, slOrderId:int, ptOrderId:int):
+ # ! [limit_order_with_stop_loss_and_protif_taker]
+ order = OrderSamples.LimitOrder(action, quantity, limitPrice)
+ order.slOrderId = slOrderId
+ order.slOrderType = "PRESET"
+ order.ptOrderId = ptOrderId
+ order.ptOrderType = "PRESET"
+ # ! [limit_order_with_stop_loss_and_protif_taker]
+ return order;
+
+def Test():
+ os = OrderSamples() # @UnusedVariable
+
+if "__main__" == __name__:
+ Test()
+
diff --git a/packages/ibkr/ref/samples/Python/Testbed/Program.py b/packages/ibkr/ref/samples/Python/Testbed/Program.py
new file mode 100644
index 00000000..1f7f0992
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/Program.py
@@ -0,0 +1,2924 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import argparse
+import datetime
+import collections
+import inspect
+
+import logging
+import time
+import os.path
+
+from ibapi import wrapper
+from ibapi.client import EClient
+from ibapi.utils import getTimeStrFromMillis, longMaxString, decimalMaxString, getEnumTypeName
+from ibapi.utils import iswrapper
+
+# types
+from ibapi.common import * # @UnusedWildImport
+from ibapi.order_condition import * # @UnusedWildImport
+from ibapi.contract import * # @UnusedWildImport
+from ibapi.order import * # @UnusedWildImport
+from ibapi.order_state import * # @UnusedWildImport
+from ibapi.execution import Execution
+from ibapi.execution import ExecutionFilter
+from ibapi.commission_and_fees_report import CommissionAndFeesReport
+from ibapi.ticktype import * # @UnusedWildImport
+from ibapi.tag_value import TagValue
+
+from ibapi.account_summary_tags import *
+
+from ConfigSamples import ConfigSamples
+from ContractSamples import ContractSamples
+from OrderSamples import OrderSamples
+from AvailableAlgoParams import AvailableAlgoParams
+from ScannerSubscriptionSamples import ScannerSubscriptionSamples
+from FaAllocationSamples import FaAllocationSamples
+from ibapi.scanner import ScanData
+from decimal import Decimal
+
+from ibapi.protobuf.OrderStatus_pb2 import OrderStatus as OrderStatusProto
+from ibapi.protobuf.OpenOrder_pb2 import OpenOrder as OpenOrderProto
+from ibapi.protobuf.OpenOrdersEnd_pb2 import OpenOrdersEnd as OpenOrdersEndProto
+from ibapi.protobuf.ErrorMessage_pb2 import ErrorMessage as ErrorMessageProto
+from ibapi.protobuf.ExecutionDetails_pb2 import ExecutionDetails as ExecutionDetailsProto
+from ibapi.protobuf.ExecutionDetailsEnd_pb2 import ExecutionDetailsEnd as ExecutionDetailsEndProto
+from ibapi.protobuf.ExecutionRequest_pb2 import ExecutionRequest as ExecutionRequestProto
+from ibapi.protobuf.ExecutionFilter_pb2 import ExecutionFilter as ExecutionFilterProto
+from ibapi.protobuf.CompletedOrder_pb2 import CompletedOrder as CompletedOrderProto
+from ibapi.protobuf.CompletedOrdersEnd_pb2 import CompletedOrdersEnd as CompletedOrdersEndProto
+from ibapi.protobuf.OrderBound_pb2 import OrderBound as OrderBoundProto
+from ibapi.protobuf.ContractData_pb2 import ContractData as ContractDataProto
+from ibapi.protobuf.ContractDataEnd_pb2 import ContractDataEnd as ContractDataEndProto
+from ibapi.protobuf.TickPrice_pb2 import TickPrice as TickPriceProto
+from ibapi.protobuf.TickSize_pb2 import TickSize as TickSizeProto
+from ibapi.protobuf.TickOptionComputation_pb2 import TickOptionComputation as TickOptionComputationProto
+from ibapi.protobuf.TickGeneric_pb2 import TickGeneric as TickGenericProto
+from ibapi.protobuf.TickString_pb2 import TickString as TickStringProto
+from ibapi.protobuf.TickSnapshotEnd_pb2 import TickSnapshotEnd as TickSnapshotEndProto
+from ibapi.protobuf.MarketDepth_pb2 import MarketDepth as MarketDepthProto
+from ibapi.protobuf.MarketDepthL2_pb2 import MarketDepthL2 as MarketDepthL2Proto
+from ibapi.protobuf.MarketDataType_pb2 import MarketDataType as MarketDataTypeProto
+from ibapi.protobuf.TickReqParams_pb2 import TickReqParams as TickReqParamsProto
+from ibapi.protobuf.AccountValue_pb2 import AccountValue as AccountValueProto
+from ibapi.protobuf.PortfolioValue_pb2 import PortfolioValue as PortfolioValueProto
+from ibapi.protobuf.AccountUpdateTime_pb2 import AccountUpdateTime as AccountUpdateTimeProto
+from ibapi.protobuf.AccountDataEnd_pb2 import AccountDataEnd as AccountDataEndProto
+from ibapi.protobuf.ManagedAccounts_pb2 import ManagedAccounts as ManagedAccountsProto
+from ibapi.protobuf.Position_pb2 import Position as PositionProto
+from ibapi.protobuf.PositionEnd_pb2 import PositionEnd as PositionEndProto
+from ibapi.protobuf.AccountSummary_pb2 import AccountSummary as AccountSummaryProto
+from ibapi.protobuf.AccountSummaryEnd_pb2 import AccountSummaryEnd as AccountSummaryEndProto
+from ibapi.protobuf.PositionMulti_pb2 import PositionMulti as PositionMultiProto
+from ibapi.protobuf.PositionMultiEnd_pb2 import PositionMultiEnd as PositionMultiEndProto
+from ibapi.protobuf.AccountUpdateMulti_pb2 import AccountUpdateMulti as AccountUpdateMultiProto
+from ibapi.protobuf.AccountUpdateMultiEnd_pb2 import AccountUpdateMultiEnd as AccountUpdateMultiEndProto
+from ibapi.protobuf.HistoricalData_pb2 import HistoricalData as HistoricalDataProto
+from ibapi.protobuf.HistoricalDataUpdate_pb2 import HistoricalDataUpdate as HistoricalDataUpdateProto
+from ibapi.protobuf.HistoricalDataEnd_pb2 import HistoricalDataEnd as HistoricalDataEndProto
+from ibapi.protobuf.RealTimeBarTick_pb2 import RealTimeBarTick as RealTimeBarTickProto
+from ibapi.protobuf.HeadTimestamp_pb2 import HeadTimestamp as HeadTimestampProto
+from ibapi.protobuf.HistogramData_pb2 import HistogramData as HistogramDataProto
+from ibapi.protobuf.HistoricalTicks_pb2 import HistoricalTicks as HistoricalTicksProto
+from ibapi.protobuf.HistoricalTicksBidAsk_pb2 import HistoricalTicksBidAsk as HistoricalTicksBidAskProto
+from ibapi.protobuf.HistoricalTicksLast_pb2 import HistoricalTicksLast as HistoricalTicksLastProto
+from ibapi.protobuf.TickByTickData_pb2 import TickByTickData as TickByTickDataProto
+from ibapi.protobuf.NewsBulletin_pb2 import NewsBulletin as NewsBulletinProto
+from ibapi.protobuf.NewsArticle_pb2 import NewsArticle as NewsArticleProto
+from ibapi.protobuf.NewsProviders_pb2 import NewsProviders as NewsProvidersProto
+from ibapi.protobuf.HistoricalNews_pb2 import HistoricalNews as HistoricalNewsProto
+from ibapi.protobuf.HistoricalNewsEnd_pb2 import HistoricalNewsEnd as HistoricalNewsEndProto
+from ibapi.protobuf.WshMetaData_pb2 import WshMetaData as WshMetaDataProto
+from ibapi.protobuf.WshEventData_pb2 import WshEventData as WshEventDataProto
+from ibapi.protobuf.TickNews_pb2 import TickNews as TickNewsProto
+from ibapi.protobuf.ScannerParameters_pb2 import ScannerParameters as ScannerParametersProto
+from ibapi.protobuf.ScannerData_pb2 import ScannerData as ScannerDataProto
+from ibapi.protobuf.FundamentalsData_pb2 import FundamentalsData as FundamentalsDataProto
+from ibapi.protobuf.PnL_pb2 import PnL as PnLProto
+from ibapi.protobuf.PnLSingle_pb2 import PnLSingle as PnLSingleProto
+from ibapi.protobuf.ReceiveFA_pb2 import ReceiveFA as ReceiveFAProto
+from ibapi.protobuf.ReplaceFAEnd_pb2 import ReplaceFAEnd as ReplaceFAEndProto
+from ibapi.protobuf.CommissionAndFeesReport_pb2 import CommissionAndFeesReport as CommissionAndFeesReportProto
+from ibapi.protobuf.HistoricalSchedule_pb2 import HistoricalSchedule as HistoricalScheduleProto
+from ibapi.protobuf.RerouteMarketDataRequest_pb2 import RerouteMarketDataRequest as RerouteMarketDataRequestProto
+from ibapi.protobuf.RerouteMarketDepthRequest_pb2 import RerouteMarketDepthRequest as RerouteMarketDepthRequestProto
+from ibapi.protobuf.SecDefOptParameter_pb2 import SecDefOptParameter as SecDefOptParameterProto
+from ibapi.protobuf.SecDefOptParameterEnd_pb2 import SecDefOptParameterEnd as SecDefOptParameterEndProto
+from ibapi.protobuf.SoftDollarTiers_pb2 import SoftDollarTiers as SoftDollarTiersProto
+from ibapi.protobuf.FamilyCodes_pb2 import FamilyCodes as FamilyCodesProto
+from ibapi.protobuf.SymbolSamples_pb2 import SymbolSamples as SymbolSamplesProto
+from ibapi.protobuf.SmartComponents_pb2 import SmartComponents as SmartComponentsProto
+from ibapi.protobuf.MarketRule_pb2 import MarketRule as MarketRuleProto
+from ibapi.protobuf.UserInfo_pb2 import UserInfo as UserInfoProto
+from ibapi.protobuf.NextValidId_pb2 import NextValidId as NextValidIdProto
+from ibapi.protobuf.CurrentTime_pb2 import CurrentTime as CurrentTimeProto
+from ibapi.protobuf.CurrentTimeInMillis_pb2 import CurrentTimeInMillis as CurrentTimeInMillisProto
+from ibapi.protobuf.VerifyMessageApi_pb2 import VerifyMessageApi as VerifyMessageApiProto
+from ibapi.protobuf.VerifyCompleted_pb2 import VerifyCompleted as VerifyCompletedProto
+from ibapi.protobuf.DisplayGroupList_pb2 import DisplayGroupList as DisplayGroupListProto
+from ibapi.protobuf.DisplayGroupUpdated_pb2 import DisplayGroupUpdated as DisplayGroupUpdatedProto
+from ibapi.protobuf.MarketDepthExchanges_pb2 import MarketDepthExchanges as MarketDepthExchangesProto
+from ibapi.protobuf.ConfigRequest_pb2 import ConfigRequest as ConfigRequestProto
+from ibapi.protobuf.ConfigResponse_pb2 import ConfigResponse as ConfigResponseProto
+from ibapi.protobuf.UpdateConfigResponse_pb2 import UpdateConfigResponse as UpdateConfigResponseProto
+
+def SetupLogger():
+ if not os.path.exists("log"):
+ os.makedirs("log")
+
+ time.strftime("pyibapi.%Y%m%d_%H%M%S.log")
+
+ recfmt = '(%(threadName)s) %(asctime)s.%(msecs)03d %(levelname)s %(filename)s:%(lineno)d %(message)s'
+
+ timefmt = '%y%m%d_%H:%M:%S'
+
+ # logging.basicConfig( level=logging.DEBUG,
+ # format=recfmt, datefmt=timefmt)
+ logging.basicConfig(filename=time.strftime("log/pyibapi.%y%m%d_%H%M%S.log"),
+ filemode="w",
+ level=logging.INFO,
+ format=recfmt, datefmt=timefmt)
+ logger = logging.getLogger()
+ console = logging.StreamHandler()
+ console.setLevel(logging.ERROR)
+ logger.addHandler(console)
+
+
+def printWhenExecuting(fn):
+ def fn2(self):
+ print(" doing", fn.__name__)
+ fn(self)
+ print(" done w/", fn.__name__)
+
+ return fn2
+
+def printinstance(inst:Object):
+ attrs = vars(inst)
+ print(', '.join('{}:{}'.format(key, decimalMaxString(value) if type(value) is Decimal else
+ floatMaxString(value) if type(value) is float else
+ intMaxString(value) if type(value) is int else
+ getEnumTypeName(FundAssetType, value) if type(value) is FundAssetType else
+ getEnumTypeName(FundDistributionPolicyIndicator, value) if type(value) is FundDistributionPolicyIndicator else
+ "{%s}" % "; ".join(map(str, value)) if type(value) is list else
+ value) for key, value in attrs.items()))
+
+class Activity(Object):
+ def __init__(self, reqMsgId, ansMsgId, ansEndMsgId, reqId):
+ self.reqMsdId = reqMsgId
+ self.ansMsgId = ansMsgId
+ self.ansEndMsgId = ansEndMsgId
+ self.reqId = reqId
+
+
+class RequestMgr(Object):
+ def __init__(self):
+ # I will keep this simple even if slower for now: only one list of
+ # requests finding will be done by linear search
+ self.requests = []
+
+ def addReq(self, req):
+ self.requests.append(req)
+
+ def receivedMsg(self, msg):
+ pass
+
+
+# ! [socket_declare]
+class TestClient(EClient):
+ def __init__(self, wrapper):
+ EClient.__init__(self, wrapper)
+ # ! [socket_declare]
+
+ # how many times a method is called to see test coverage
+ self.clntMeth2callCount = collections.defaultdict(int)
+ self.clntMeth2reqIdIdx = collections.defaultdict(lambda: -1)
+ self.reqId2nReq = collections.defaultdict(int)
+ self.setupDetectReqId()
+
+ def countReqId(self, methName, fn):
+ def countReqId_(*args, **kwargs):
+ self.clntMeth2callCount[methName] += 1
+ idx = self.clntMeth2reqIdIdx[methName]
+ if idx >= 0:
+ sign = -1 if 'cancel' in methName else 1
+ self.reqId2nReq[sign * args[idx]] += 1
+ return fn(*args, **kwargs)
+
+ return countReqId_
+
+ def setupDetectReqId(self):
+
+ methods = inspect.getmembers(EClient, inspect.isfunction)
+ for (methName, meth) in methods:
+ if methName != "send_msg":
+ # don't screw up the nice automated logging in the send_msg()
+ self.clntMeth2callCount[methName] = 0
+ # logging.debug("meth %s", name)
+ sig = inspect.signature(meth)
+ for (idx, pnameNparam) in enumerate(sig.parameters.items()):
+ (paramName, param) = pnameNparam # @UnusedVariable
+ if paramName == "reqId":
+ self.clntMeth2reqIdIdx[methName] = idx
+
+ setattr(TestClient, methName, self.countReqId(methName, meth))
+
+ # print("TestClient.clntMeth2reqIdIdx", self.clntMeth2reqIdIdx)
+
+
+# ! [ewrapperimpl]
+class TestWrapper(wrapper.EWrapper):
+ # ! [ewrapperimpl]
+ def __init__(self):
+ wrapper.EWrapper.__init__(self)
+
+ self.wrapMeth2callCount = collections.defaultdict(int)
+ self.wrapMeth2reqIdIdx = collections.defaultdict(lambda: -1)
+ self.reqId2nAns = collections.defaultdict(int)
+ self.setupDetectWrapperReqId()
+
+ # TODO: see how to factor this out !!
+
+ def countWrapReqId(self, methName, fn):
+ def countWrapReqId_(*args, **kwargs):
+ self.wrapMeth2callCount[methName] += 1
+ idx = self.wrapMeth2reqIdIdx[methName]
+ if idx >= 0:
+ self.reqId2nAns[args[idx]] += 1
+ return fn(*args, **kwargs)
+
+ return countWrapReqId_
+
+ def setupDetectWrapperReqId(self):
+
+ methods = inspect.getmembers(wrapper.EWrapper, inspect.isfunction)
+ for (methName, meth) in methods:
+ self.wrapMeth2callCount[methName] = 0
+ # logging.debug("meth %s", name)
+ sig = inspect.signature(meth)
+ for (idx, pnameNparam) in enumerate(sig.parameters.items()):
+ (paramName, param) = pnameNparam # @UnusedVariable
+ # we want to count the errors as 'error' not 'answer'
+ if 'error' not in methName and paramName == "reqId":
+ self.wrapMeth2reqIdIdx[methName] = idx
+
+ setattr(TestWrapper, methName, self.countWrapReqId(methName, meth))
+
+ # print("TestClient.wrapMeth2reqIdIdx", self.wrapMeth2reqIdIdx)
+
+
+# this is here for documentation generation
+"""
+#! [ereader]
+ # You don't need to run this in your code!
+ self.reader = reader.EReader(self.conn, self.msg_queue)
+ self.reader.start() # start thread
+#! [ereader]
+"""
+
+# ! [socket_init]
+class TestApp(TestWrapper, TestClient):
+ def __init__(self):
+ TestWrapper.__init__(self)
+ TestClient.__init__(self, wrapper=self)
+ # ! [socket_init]
+ self.nKeybInt = 0
+ self.started = False
+ self.nextValidOrderId = None
+ self.permId2ord = {}
+ self.reqId2nErr = collections.defaultdict(int)
+ self.globalCancelOnly = False
+ self.simplePlaceOid = None
+
+ def dumpTestCoverageSituation(self):
+ for clntMeth in sorted(self.clntMeth2callCount.keys()):
+ logging.debug("ClntMeth: %-30s %6d" % (clntMeth,
+ self.clntMeth2callCount[clntMeth]))
+
+ for wrapMeth in sorted(self.wrapMeth2callCount.keys()):
+ logging.debug("WrapMeth: %-30s %6d" % (wrapMeth,
+ self.wrapMeth2callCount[wrapMeth]))
+
+ def dumpReqAnsErrSituation(self):
+ logging.debug("%s\t%s\t%s\t%s" % ("ReqId", "#Req", "#Ans", "#Err"))
+ for reqId in sorted(self.reqId2nReq.keys()):
+ nReq = self.reqId2nReq.get(reqId, 0)
+ nAns = self.reqId2nAns.get(reqId, 0)
+ nErr = self.reqId2nErr.get(reqId, 0)
+ logging.debug("%d\t%d\t%s\t%d" % (reqId, nReq, nAns, nErr))
+
+ @iswrapper
+ # ! [connectack]
+ def connectAck(self):
+ if self.asynchronous:
+ self.startApi()
+
+ # ! [connectack]
+
+ @iswrapper
+ # ! [nextvalidid]
+ def nextValidId(self, orderId: int):
+ super().nextValidId(orderId)
+
+ logging.debug("setting nextValidOrderId: %d", orderId)
+ self.nextValidOrderId = orderId
+ print("NextValidId:", orderId)
+ # ! [nextvalidid]
+
+ # we can start now
+ if hasattr(self, 'account'):
+ self.start()
+
+ def start(self):
+ if self.started:
+ return
+
+ self.started = True
+
+ if self.globalCancelOnly:
+ print("Executing GlobalCancel only")
+ self.reqGlobalCancel(OrderSamples.CancelOrderEmpty())
+ else:
+ print("Executing requests")
+ #self.reqGlobalCancel(OrderSamples.CancelOrderEmpty()))
+ #self.marketDataTypeOperations()
+ #self.accountOperations_req()
+ #self.tickDataOperations_req()
+ #self.tickOptionComputations_req()
+ #self.marketDepthOperations_req()
+ #self.realTimeBarsOperations_req()
+ #self.historicalDataOperations_req()
+ #self.optionsOperations_req()
+ #self.marketScannersOperations_req()
+ #self.fundamentalsOperations_req()
+ #self.bulletinsOperations_req()
+ #self.contractOperations_req()
+ #self.newsOperations_req()
+ #self.miscelaneousOperations()
+ #self.linkingOperations()
+ #self.financialAdvisorOperations()
+ #self.orderOperations_req()
+ #self.rerouteCFDOperations()
+ #self.marketRuleOperations()
+ #self.pnlOperations_req()
+ #self.histogramOperations_req()
+ #self.continuousFuturesOperations_req()
+ #self.historicalTicksOperations_req()
+ #self.tickByTickOperations_req()
+ #self.whatIfOrderOperations()
+ #self.wshCalendarOperations()
+ #self.algoSamples()
+ #self.conditionSamples()
+ self.configOperations_req()
+
+
+ print("Executing requests ... finished")
+
+ def keyboardInterrupt(self):
+ self.nKeybInt += 1
+ if self.nKeybInt == 1:
+ self.stop()
+ else:
+ print("Finishing test")
+ self.done = True
+
+ def stop(self):
+ print("Executing cancels")
+ #self.orderOperations_cancel()
+ #self.accountOperations_cancel()
+ #self.tickDataOperations_cancel()
+ #self.tickOptionComputations_cancel()
+ #self.marketDepthOperations_cancel()
+ #self.realTimeBarsOperations_cancel()
+ #self.historicalDataOperations_cancel()
+ #self.optionsOperations_cancel()
+ #self.marketScanners_cancel()
+ #self.fundamentalsOperations_cancel()
+ #self.bulletinsOperations_cancel()
+ #self.newsOperations_cancel()
+ #self.pnlOperations_cancel()
+ #self.histogramOperations_cancel()
+ #self.continuousFuturesOperations_cancel()
+ #self.tickByTickOperations_cancel()
+ #self.contractOperations_cancel()
+ #self.historicalTicksOperations_cancel()
+ print("Executing cancels ... finished")
+
+ def nextOrderId(self):
+ oid = self.nextValidOrderId
+ self.nextValidOrderId += 1
+ return oid
+
+ @iswrapper
+ # ! [error]
+ def error(self, reqId: TickerId, errorTime: int, errorCode: int, errorString: str, advancedOrderRejectJson = ""):
+ errorTimeStr = getTimeStrFromMillis(errorTime)
+ if advancedOrderRejectJson:
+ print("Error. Id:", reqId, "Time:", errorTimeStr, "Code:", errorCode, "Msg:", errorString, "AdvancedOrderRejectJson:", advancedOrderRejectJson)
+ else:
+ print("Error. Id:", reqId, "Time:", errorTimeStr, "Code:", errorCode, "Msg:", errorString)
+
+ # ! [error] self.reqId2nErr[reqId] += 1
+
+
+ @iswrapper
+ def winError(self, text: str, lastError: int):
+ super().winError(text, lastError)
+
+ @iswrapper
+ # ! [openorder]
+ def openOrder(self, orderId: OrderId, contract: Contract, order: Order,
+ orderState: OrderState):
+ super().openOrder(orderId, contract, order, orderState)
+ print("OpenOrder. PermId:", longMaxString(order.permId), "ClientId:", intMaxString(order.clientId), " OrderId:", intMaxString(orderId),
+ "Account:", order.account, "Symbol:", contract.symbol, "SecType:", contract.secType, "Strike:", floatMaxString(contract.strike),
+ "Exchange:", contract.exchange, "Action:", order.action, "OrderType:", order.orderType,
+ "TotalQty:", decimalMaxString(order.totalQuantity), "CashQty:", floatMaxString(order.cashQty),
+ "LmtPrice:", floatMaxString(order.lmtPrice), "AuxPrice:", floatMaxString(order.auxPrice), "Status:", orderState.status,
+ "MinTradeQty:", intMaxString(order.minTradeQty), "MinCompeteSize:", intMaxString(order.minCompeteSize),
+ "competeAgainstBestOffset:", "UpToMid" if order.competeAgainstBestOffset == COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID else floatMaxString(order.competeAgainstBestOffset),
+ "MidOffsetAtWhole:", floatMaxString(order.midOffsetAtWhole),"MidOffsetAtHalf:" ,floatMaxString(order.midOffsetAtHalf),
+ "FAGroup:", order.faGroup, "FAMethod:", order.faMethod, "CustomerAccount:", order.customerAccount, "ProfessionalCustomer:", order.professionalCustomer,
+ "BondAccruedInterest:", order.bondAccruedInterest, "IncludeOvernight:", order.includeOvernight, "ExtOperator:", order.extOperator,
+ "ManualOrderIndicator:", intMaxString(order.manualOrderIndicator), "Submitter:", order.submitter, "ImbalanceOnly:", order.imbalanceOnly, "AlgoStrategy:", order.algoStrategy,
+ "PostOnly:", order.postOnly, "AllowPreOpen:", order.allowPreOpen, "IgnoreOpenAuction:", order.ignoreOpenAuction, "Deactivate:", order.deactivate,
+ "ActiveStartTime:", order.activeStartTime, "ActiveStopTime:", order.activeStopTime, "SeekPriceImprovement:", ("True" if order.seekPriceImprovement else "False"),
+ "WhatIfType:", order.whatIfType, "RouteMarketableToBbo:", ("True" if order.routeMarketableToBbo else "False"))
+
+ self.printTagValueList(order.algoParams, "AlgoParams")
+ self.printComboLegs(contract.comboLegs)
+ self.printOrderComboLegs(order.orderComboLegs)
+ self.printDeltaNeutralContract(contract.deltaNeutralContract)
+ self.printTagValueList(order.smartComboRoutingParams, "SmartComboRoutingParams")
+ self.printConditions(order.conditions)
+ self.printSoftDollarTier(order.softDollarTier)
+
+ if order.whatIf:
+ print(orderState)
+
+ order.contract = contract
+ self.permId2ord[order.permId] = order
+ # ! [openorder]
+
+ @iswrapper
+ # ! [openorderend]
+ def openOrderEnd(self):
+ super().openOrderEnd()
+ print("OpenOrderEnd")
+
+ logging.debug("Received %d openOrders", len(self.permId2ord))
+ # ! [openorderend]
+
+ @iswrapper
+ # ! [orderstatus]
+ def orderStatus(self, orderId: OrderId, status: str, filled: Decimal,
+ remaining: Decimal, avgFillPrice: float, permId: int,
+ parentId: int, lastFillPrice: float, clientId: int,
+ whyHeld: str, mktCapPrice: float):
+ super().orderStatus(orderId, status, filled, remaining,
+ avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice)
+ print("OrderStatus. Id:", orderId, "Status:", status, "Filled:", decimalMaxString(filled),
+ "Remaining:", decimalMaxString(remaining), "AvgFillPrice:", floatMaxString(avgFillPrice),
+ "PermId:", longMaxString(permId), "ParentId:", intMaxString(parentId), "LastFillPrice:",
+ floatMaxString(lastFillPrice), "ClientId:", intMaxString(clientId), "WhyHeld:",
+ whyHeld, "MktCapPrice:", floatMaxString(mktCapPrice))
+ # ! [orderstatus]
+
+
+ @printWhenExecuting
+ def accountOperations_req(self):
+ # Requesting managed accounts
+ # ! [reqmanagedaccts]
+ self.reqManagedAccts()
+ # ! [reqmanagedaccts]
+
+ # Requesting family codes
+ # ! [reqfamilycodes]
+ self.reqFamilyCodes()
+ # ! [reqfamilycodes]
+
+ # Requesting accounts' summary
+ # ! [reqaaccountsummary]
+ self.reqAccountSummary(9001, "All", AccountSummaryTags.AllTags)
+ # ! [reqaaccountsummary]
+
+ # ! [reqaaccountsummaryledger]
+ self.reqAccountSummary(9002, "All", "$LEDGER")
+ # ! [reqaaccountsummaryledger]
+
+ # ! [reqaaccountsummaryledgercurrency]
+ self.reqAccountSummary(9003, "All", "$LEDGER:EUR")
+ # ! [reqaaccountsummaryledgercurrency]
+
+ # ! [reqaaccountsummaryledgerall]
+ self.reqAccountSummary(9004, "All", "$LEDGER:ALL")
+ # ! [reqaaccountsummaryledgerall]
+
+ # Subscribing to an account's information. Only one at a time!
+ # ! [reqaaccountupdates]
+ self.reqAccountUpdates(True, self.account)
+ # ! [reqaaccountupdates]
+
+ # ! [reqaaccountupdatesmulti]
+ self.reqAccountUpdatesMulti(9005, self.account, "", True)
+ # ! [reqaaccountupdatesmulti]
+
+ # Requesting all accounts' positions.
+ # ! [reqpositions]
+ self.reqPositions()
+ # ! [reqpositions]
+
+ # ! [reqpositionsmulti]
+ self.reqPositionsMulti(9006, self.account, "")
+ # ! [reqpositionsmulti]
+
+ # ! [requserinfo]
+ self.reqUserInfo(0)
+ # ! [requserinfo]
+
+ @printWhenExecuting
+ def accountOperations_cancel(self):
+ # ! [cancelaaccountsummary]
+ self.cancelAccountSummary(9001)
+ self.cancelAccountSummary(9002)
+ self.cancelAccountSummary(9003)
+ self.cancelAccountSummary(9004)
+ # ! [cancelaaccountsummary]
+
+ # ! [cancelaaccountupdates]
+ self.reqAccountUpdates(False, self.account)
+ # ! [cancelaaccountupdates]
+
+ # ! [cancelaaccountupdatesmulti]
+ self.cancelAccountUpdatesMulti(9005)
+ # ! [cancelaaccountupdatesmulti]
+
+ # ! [cancelpositions]
+ self.cancelPositions()
+ # ! [cancelpositions]
+
+ # ! [cancelpositionsmulti]
+ self.cancelPositionsMulti(9006)
+ # ! [cancelpositionsmulti]
+
+ def pnlOperations_req(self):
+ # ! [reqpnl]
+ self.reqPnL(17001, "DU111519", "")
+ # ! [reqpnl]
+
+ # ! [reqpnlsingle]
+ self.reqPnLSingle(17002, "DU111519", "", 8314)
+ # ! [reqpnlsingle]
+
+ def pnlOperations_cancel(self):
+ # ! [cancelpnl]
+ self.cancelPnL(17001)
+ # ! [cancelpnl]
+
+ # ! [cancelpnlsingle]
+ self.cancelPnLSingle(17002)
+ # ! [cancelpnlsingle]
+
+ def histogramOperations_req(self):
+ # ! [reqhistogramdata]
+ self.reqHistogramData(4002, ContractSamples.USStockAtSmart(), False, "3 days")
+ # ! [reqhistogramdata]
+
+ def histogramOperations_cancel(self):
+ # ! [cancelhistogramdata]
+ self.cancelHistogramData(4002)
+ # ! [cancelhistogramdata]
+
+ def continuousFuturesOperations_req(self):
+ # ! [reqcontractdetailscontfut]
+ self.reqContractDetails(18001, ContractSamples.ContFut())
+ # ! [reqcontractdetailscontfut]
+
+ # ! [reqhistoricaldatacontfut]
+ self.reqHistoricalData(18002, ContractSamples.ContFut(), "", "1 Y", "1 month", "TRADES", 0, 1, False, [])
+ # ! [reqhistoricaldatacontfut]
+
+ def continuousFuturesOperations_cancel(self):
+ # ! [cancelhistoricaldatacontfut]
+ self.cancelHistoricalData(18002)
+ # ! [cancelhistoricaldatacontfut]
+
+ @iswrapper
+ # ! [managedaccounts]
+ def managedAccounts(self, accountsList: str):
+ super().managedAccounts(accountsList)
+ print("Account list:", accountsList)
+ # ! [managedaccounts]
+
+ self.account = accountsList.split(",")[0]
+
+ if self.nextValidOrderId is not None:
+ self.start()
+
+ @iswrapper
+ # ! [accountsummary]
+ def accountSummary(self, reqId: int, account: str, tag: str, value: str,
+ currency: str):
+ super().accountSummary(reqId, account, tag, value, currency)
+ print("AccountSummary. ReqId:", reqId, "Account:", account,
+ "Tag: ", tag, "Value:", value, "Currency:", currency)
+ # ! [accountsummary]
+
+ @iswrapper
+ # ! [accountsummaryend]
+ def accountSummaryEnd(self, reqId: int):
+ super().accountSummaryEnd(reqId)
+ print("AccountSummaryEnd. ReqId:", reqId)
+ # ! [accountsummaryend]
+
+ @iswrapper
+ # ! [updateaccountvalue]
+ def updateAccountValue(self, key: str, val: str, currency: str,
+ accountName: str):
+ super().updateAccountValue(key, val, currency, accountName)
+ print("UpdateAccountValue. Key:", key, "Value:", val,
+ "Currency:", currency, "AccountName:", accountName)
+ # ! [updateaccountvalue]
+
+ @iswrapper
+ # ! [updateportfolio]
+ def updatePortfolio(self, contract: Contract, position: Decimal,
+ marketPrice: float, marketValue: float,
+ averageCost: float, unrealizedPNL: float,
+ realizedPNL: float, accountName: str):
+ super().updatePortfolio(contract, position, marketPrice, marketValue,
+ averageCost, unrealizedPNL, realizedPNL, accountName)
+ print("UpdatePortfolio.", "Symbol:", contract.symbol, "SecType:", contract.secType, "Exchange:",
+ contract.exchange, "Position:", decimalMaxString(position), "MarketPrice:", floatMaxString(marketPrice),
+ "MarketValue:", floatMaxString(marketValue), "AverageCost:", floatMaxString(averageCost),
+ "UnrealizedPNL:", floatMaxString(unrealizedPNL), "RealizedPNL:", floatMaxString(realizedPNL),
+ "AccountName:", accountName)
+ # ! [updateportfolio]
+
+ @iswrapper
+ # ! [updateaccounttime]
+ def updateAccountTime(self, timeStamp: str):
+ super().updateAccountTime(timeStamp)
+ print("UpdateAccountTime. Time:", timeStamp)
+ # ! [updateaccounttime]
+
+ @iswrapper
+ # ! [accountdownloadend]
+ def accountDownloadEnd(self, accountName: str):
+ super().accountDownloadEnd(accountName)
+ print("AccountDownloadEnd. Account:", accountName)
+ # ! [accountdownloadend]
+
+ @iswrapper
+ # ! [position]
+ def position(self, account: str, contract: Contract, position: Decimal,
+ avgCost: float):
+ super().position(account, contract, position, avgCost)
+ print("Position.", "Account:", account, "Symbol:", contract.symbol, "SecType:",
+ contract.secType, "Currency:", contract.currency,
+ "Position:", decimalMaxString(position), "Avg cost:", floatMaxString(avgCost))
+ # ! [position]
+
+ @iswrapper
+ # ! [positionend]
+ def positionEnd(self):
+ super().positionEnd()
+ print("PositionEnd")
+ # ! [positionend]
+
+ @iswrapper
+ # ! [positionmulti]
+ def positionMulti(self, reqId: int, account: str, modelCode: str,
+ contract: Contract, pos: Decimal, avgCost: float):
+ super().positionMulti(reqId, account, modelCode, contract, pos, avgCost)
+ print("PositionMulti. RequestId:", reqId, "Account:", account,
+ "ModelCode:", modelCode, "Symbol:", contract.symbol, "SecType:",
+ contract.secType, "Currency:", contract.currency, ",Position:",
+ decimalMaxString(pos), "AvgCost:", floatMaxString(avgCost))
+ # ! [positionmulti]
+
+ @iswrapper
+ # ! [positionmultiend]
+ def positionMultiEnd(self, reqId: int):
+ super().positionMultiEnd(reqId)
+ print("PositionMultiEnd. RequestId:", reqId)
+ # ! [positionmultiend]
+
+ @iswrapper
+ # ! [accountupdatemulti]
+ def accountUpdateMulti(self, reqId: int, account: str, modelCode: str,
+ key: str, value: str, currency: str):
+ super().accountUpdateMulti(reqId, account, modelCode, key, value,
+ currency)
+ print("AccountUpdateMulti. RequestId:", reqId, "Account:", account,
+ "ModelCode:", modelCode, "Key:", key, "Value:", value,
+ "Currency:", currency)
+ # ! [accountupdatemulti]
+
+ @iswrapper
+ # ! [accountupdatemultiend]
+ def accountUpdateMultiEnd(self, reqId: int):
+ super().accountUpdateMultiEnd(reqId)
+ print("AccountUpdateMultiEnd. RequestId:", reqId)
+ # ! [accountupdatemultiend]
+
+ @iswrapper
+ # ! [familyCodes]
+ def familyCodes(self, familyCodes: ListOfFamilyCode):
+ super().familyCodes(familyCodes)
+ print("Family Codes:")
+ for familyCode in familyCodes:
+ print("FamilyCode.", familyCode)
+ # ! [familyCodes]
+
+ @iswrapper
+ # ! [pnl]
+ def pnl(self, reqId: int, dailyPnL: float,
+ unrealizedPnL: float, realizedPnL: float):
+ super().pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL)
+ print("Daily PnL. ReqId:", reqId, "DailyPnL:", floatMaxString(dailyPnL),
+ "UnrealizedPnL:", floatMaxString(unrealizedPnL), "RealizedPnL:", floatMaxString(realizedPnL))
+ # ! [pnl]
+
+ @iswrapper
+ # ! [pnlsingle]
+ def pnlSingle(self, reqId: int, pos: Decimal, dailyPnL: float,
+ unrealizedPnL: float, realizedPnL: float, value: float):
+ super().pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value)
+ print("Daily PnL Single. ReqId:", reqId, "Position:", decimalMaxString(pos),
+ "DailyPnL:", floatMaxString(dailyPnL), "UnrealizedPnL:", floatMaxString(unrealizedPnL),
+ "RealizedPnL:", floatMaxString(realizedPnL), "Value:", floatMaxString(value))
+ # ! [pnlsingle]
+
+ def marketDataTypeOperations(self):
+ # ! [reqmarketdatatype]
+ # Switch to live (1) frozen (2) delayed (3) delayed frozen (4).
+ self.reqMarketDataType(MarketDataTypeEnum.DELAYED)
+ # ! [reqmarketdatatype]
+
+ @iswrapper
+ # ! [marketdatatype]
+ def marketDataType(self, reqId: TickerId, marketDataType: int):
+ super().marketDataType(reqId, marketDataType)
+ print("MarketDataType. ReqId:", reqId, "Type:", marketDataType)
+ # ! [marketdatatype]
+
+ @printWhenExecuting
+ def tickDataOperations_req(self):
+ self.reqMarketDataType(MarketDataTypeEnum.DELAYED_FROZEN)
+
+ # Requesting real time market data
+
+ # ! [reqmktdata]
+ self.reqMktData(1000, ContractSamples.USStockAtSmart(), "", False, False, [])
+ self.reqMktData(1001, ContractSamples.StockComboContract(), "", False, False, [])
+ # ! [reqmktdata]
+
+ # ! [reqmktdata_snapshot]
+ self.reqMktData(1002, ContractSamples.FutureComboContract(), "", True, False, [])
+ # ! [reqmktdata_snapshot]
+
+ # ! [regulatorysnapshot]
+ # Each regulatory snapshot request incurs a 0.01 USD fee
+ self.reqMktData(1003, ContractSamples.USStock(), "", False, True, [])
+ # ! [regulatorysnapshot]
+
+ # ! [reqmktdata_genticks]
+ # Requesting RTVolume (Time & Sales) and shortable generic ticks
+ self.reqMktData(1004, ContractSamples.USStockAtSmart(), "233,236", False, False, [])
+ # ! [reqmktdata_genticks]
+
+ # ! [reqmktdata_contractnews]
+ # Without the API news subscription this will generate an "invalid tick type" error
+ self.reqMktData(1005, ContractSamples.USStockAtSmart(), "mdoff,292:BRFG", False, False, [])
+ self.reqMktData(1006, ContractSamples.USStockAtSmart(), "mdoff,292:BRFG+DJNL", False, False, [])
+ self.reqMktData(1007, ContractSamples.USStockAtSmart(), "mdoff,292:BRFUPDN", False, False, [])
+ self.reqMktData(1008, ContractSamples.USStockAtSmart(), "mdoff,292:DJ-RT", False, False, [])
+ # ! [reqmktdata_contractnews]
+
+
+ # ! [reqmktdata_broadtapenews]
+ self.reqMktData(1009, ContractSamples.BTbroadtapeNewsFeed(), "mdoff,292", False, False, [])
+ self.reqMktData(1010, ContractSamples.BZbroadtapeNewsFeed(), "mdoff,292", False, False, [])
+ self.reqMktData(1011, ContractSamples.FLYbroadtapeNewsFeed(), "mdoff,292", False, False, [])
+ # ! [reqmktdata_broadtapenews]
+
+ # ! [reqoptiondatagenticks]
+ # Requesting data for an option contract will return the greek values
+ self.reqMktData(1013, ContractSamples.OptionWithLocalSymbol(), "", False, False, [])
+ self.reqMktData(1014, ContractSamples.FuturesOnOptions(), "", False, False, [])
+
+ # ! [reqoptiondatagenticks]
+
+ # ! [reqfuturesopeninterest]
+ self.reqMktData(1015, ContractSamples.SimpleFuture(), "mdoff,588", False, False, [])
+ # ! [reqfuturesopeninterest]
+
+ # ! [reqmktdatapreopenbidask]
+ self.reqMktData(1016, ContractSamples.SimpleFuture(), "", False, False, [])
+ # ! [reqmktdatapreopenbidask]
+
+ # ! [reqavgoptvolume]
+ self.reqMktData(1017, ContractSamples.USStockAtSmart(), "mdoff,105", False, False, [])
+ # ! [reqavgoptvolume]
+
+ # ! [reqsmartcomponents]
+ # Requests description of map of single letter exchange codes to full exchange names
+ self.reqSmartComponents(1018, "a6")
+ # ! [reqsmartcomponents]
+
+ # ! [reqetfticks]
+ self.reqMktData(1019, ContractSamples.etf(), "mdoff,577,623,614", False, False, [])
+ # ! [reqetfticks]
+
+ # ! [reqetfticks]
+ self.reqMktData(1020, ContractSamples.StockWithIPOPrice(), "mdoff,586", False, False, [])
+ # ! [reqetfticks]
+
+ # ! [yieldbidask]
+ self.reqMktData(1021, ContractSamples.Bond(), "", False, False, [])
+ # ! [yieldbidask]
+
+ @printWhenExecuting
+ def tickDataOperations_cancel(self):
+ # Canceling the market data subscription
+ # ! [cancelmktdata]
+ self.cancelMktData(1000)
+ self.cancelMktData(1001)
+ # ! [cancelmktdata]
+
+ self.cancelMktData(1004)
+
+ self.cancelMktData(1005)
+ self.cancelMktData(1006)
+ self.cancelMktData(1007)
+ self.cancelMktData(1008)
+
+ self.cancelMktData(1009)
+ self.cancelMktData(1010)
+ self.cancelMktData(1011)
+ self.cancelMktData(1012)
+
+ self.cancelMktData(1013)
+ self.cancelMktData(1014)
+
+ self.cancelMktData(1015)
+
+ self.cancelMktData(1016)
+
+ self.cancelMktData(1017)
+
+ self.cancelMktData(1019)
+ self.cancelMktData(1020)
+ self.cancelMktData(1021)
+
+ @printWhenExecuting
+ def tickOptionComputations_req(self):
+ self.reqMarketDataType(MarketDataTypeEnum.DELAYED_FROZEN)
+ # Requesting options computations
+ # ! [reqoptioncomputations]
+ self.reqMktData(1000, ContractSamples.OptionWithLocalSymbol(), "", False, False, [])
+ # ! [reqoptioncomputations]
+
+ @printWhenExecuting
+ def tickOptionComputations_cancel(self):
+ # Canceling options computations
+ # ! [canceloptioncomputations]
+ self.cancelMktData(1000)
+ # ! [canceloptioncomputations]
+
+ @iswrapper
+ # ! [tickprice]
+ def tickPrice(self, reqId: TickerId, tickType: TickType, price: float,
+ attrib: TickAttrib):
+ super().tickPrice(reqId, tickType, price, attrib)
+ print("TickPrice. TickerId:", reqId, "tickType:", tickType,
+ "Price:", floatMaxString(price), "CanAutoExecute:", attrib.canAutoExecute,
+ "PastLimit:", attrib.pastLimit, end=' ')
+ if tickType == TickTypeEnum.BID or tickType == TickTypeEnum.ASK:
+ print("PreOpen:", attrib.preOpen)
+ else:
+ print()
+ # ! [tickprice]
+
+ @iswrapper
+ # ! [ticksize]
+ def tickSize(self, reqId: TickerId, tickType: TickType, size: Decimal):
+ super().tickSize(reqId, tickType, size)
+ print("TickSize. TickerId:", reqId, "TickType:", tickType, "Size: ", decimalMaxString(size))
+ # ! [ticksize]
+
+ @iswrapper
+ # ! [tickgeneric]
+ def tickGeneric(self, reqId: TickerId, tickType: TickType, value: float):
+ super().tickGeneric(reqId, tickType, value)
+ print("TickGeneric. TickerId:", reqId, "TickType:", tickType, "Value:", floatMaxString(value))
+ # ! [tickgeneric]
+
+ @iswrapper
+ # ! [tickstring]
+ def tickString(self, reqId: TickerId, tickType: TickType, value: str):
+ super().tickString(reqId, tickType, value)
+ print("TickString. TickerId:", reqId, "Type:", tickType, "Value:", value)
+ # ! [tickstring]
+
+ @iswrapper
+ # ! [ticksnapshotend]
+ def tickSnapshotEnd(self, reqId: int):
+ super().tickSnapshotEnd(reqId)
+ print("TickSnapshotEnd. TickerId:", reqId)
+ # ! [ticksnapshotend]
+
+ @iswrapper
+ # ! [rerouteMktDataReq]
+ def rerouteMktDataReq(self, reqId: int, conId: int, exchange: str):
+ super().rerouteMktDataReq(reqId, conId, exchange)
+ print("Re-route market data request. ReqId:", reqId, "ConId:", conId, "Exchange:", exchange)
+ # ! [rerouteMktDataReq]
+
+ @iswrapper
+ # ! [marketRule]
+ def marketRule(self, marketRuleId: int, priceIncrements: ListOfPriceIncrements):
+ super().marketRule(marketRuleId, priceIncrements)
+ print("Market Rule ID: ", marketRuleId)
+ for priceIncrement in priceIncrements:
+ print("Price Increment.", priceIncrement)
+ # ! [marketRule]
+
+ @printWhenExecuting
+ def tickByTickOperations_req(self):
+ # Requesting tick-by-tick data (only refresh)
+ # ! [reqtickbytick]
+ self.reqTickByTickData(19001, ContractSamples.EuropeanStock2(), "Last", 0, True)
+ self.reqTickByTickData(19002, ContractSamples.EuropeanStock2(), "AllLast", 0, False)
+ self.reqTickByTickData(19003, ContractSamples.EuropeanStock2(), "BidAsk", 0, True)
+ self.reqTickByTickData(19004, ContractSamples.EurGbpFx(), "MidPoint", 0, False)
+ # ! [reqtickbytick]
+
+ # Requesting tick-by-tick data (refresh + historicalticks)
+ # ! [reqtickbytickwithhist]
+ self.reqTickByTickData(19005, ContractSamples.EuropeanStock2(), "Last", 10, False)
+ self.reqTickByTickData(19006, ContractSamples.EuropeanStock2(), "AllLast", 10, False)
+ self.reqTickByTickData(19007, ContractSamples.EuropeanStock2(), "BidAsk", 10, False)
+ self.reqTickByTickData(19008, ContractSamples.EurGbpFx(), "MidPoint", 10, True)
+ # ! [reqtickbytickwithhist]
+
+ @printWhenExecuting
+ def tickByTickOperations_cancel(self):
+ # ! [canceltickbytick]
+ self.cancelTickByTickData(19001)
+ self.cancelTickByTickData(19002)
+ self.cancelTickByTickData(19003)
+ self.cancelTickByTickData(19004)
+ # ! [canceltickbytick]
+
+ # ! [canceltickbytickwithhist]
+ self.cancelTickByTickData(19005)
+ self.cancelTickByTickData(19006)
+ self.cancelTickByTickData(19007)
+ self.cancelTickByTickData(19008)
+ # ! [canceltickbytickwithhist]
+
+ @iswrapper
+ # ! [orderbound]
+ def orderBound(self, permId: int, clientId: int, orderId: int):
+ super().orderBound(permId, clientId, orderId)
+ print("OrderBound.", "PermId:", longMaxString(permId), "ClientId:", intMaxString(clientId), "OrderId:", intMaxString(orderId))
+ # ! [orderbound]
+
+ @iswrapper
+ # ! [tickbytickalllast]
+ def tickByTickAllLast(self, reqId: int, tickType: int, time: int, price: float,
+ size: Decimal, tickAtrribLast: TickAttribLast, exchange: str,
+ specialConditions: str):
+ super().tickByTickAllLast(reqId, tickType, time, price, size, tickAtrribLast,
+ exchange, specialConditions)
+ if tickType == 1:
+ print("Last.", end='')
+ else:
+ print("AllLast.", end='')
+ print(" ReqId:", reqId,
+ "Time:", getTimeStrFromMillis(time),
+ "Price:", floatMaxString(price), "Size:", decimalMaxString(size), "Exch:" , exchange,
+ "Spec Cond:", specialConditions, "PastLimit:", tickAtrribLast.pastLimit, "Unreported:", tickAtrribLast.unreported)
+ # ! [tickbytickalllast]
+
+ @iswrapper
+ # ! [tickbytickbidask]
+ def tickByTickBidAsk(self, reqId: int, time: int, bidPrice: float, askPrice: float,
+ bidSize: Decimal, askSize: Decimal, tickAttribBidAsk: TickAttribBidAsk):
+ super().tickByTickBidAsk(reqId, time, bidPrice, askPrice, bidSize,
+ askSize, tickAttribBidAsk)
+ print("BidAsk. ReqId:", reqId,
+ "Time:", getTimeStrFromMillis(time),
+ "BidPrice:", floatMaxString(bidPrice), "AskPrice:", floatMaxString(askPrice), "BidSize:", decimalMaxString(bidSize),
+ "AskSize:", decimalMaxString(askSize), "BidPastLow:", tickAttribBidAsk.bidPastLow, "AskPastHigh:", tickAttribBidAsk.askPastHigh)
+ # ! [tickbytickbidask]
+
+ # ! [tickbytickmidpoint]
+ @iswrapper
+ def tickByTickMidPoint(self, reqId: int, time: int, midPoint: float):
+ super().tickByTickMidPoint(reqId, time, midPoint)
+ print("Midpoint. ReqId:", reqId,
+ "Time:", getTimeStrFromMillis(time),
+ "MidPoint:", floatMaxString(midPoint))
+ # ! [tickbytickmidpoint]
+
+ @printWhenExecuting
+ def marketDepthOperations_req(self):
+ # Requesting the Deep Book
+ # ! [reqmarketdepth]
+ self.reqMktDepth(2001, ContractSamples.EurGbpFx(), 5, False, [])
+ # ! [reqmarketdepth]
+
+ # ! [reqmarketdepth]
+ self.reqMktDepth(2002, ContractSamples.EuropeanStock(), 5, True, [])
+ # ! [reqmarketdepth]
+
+ # Request list of exchanges sending market depth to UpdateMktDepthL2()
+ # ! [reqMktDepthExchanges]
+ self.reqMktDepthExchanges()
+ # ! [reqMktDepthExchanges]
+
+ @printWhenExecuting
+ def marketDepthOperations_cancel(self):
+ # Canceling the Deep Book request
+ # ! [cancelmktdepth]
+ self.cancelMktDepth(2001, False)
+ self.cancelMktDepth(2002, True)
+ # ! [cancelmktdepth]
+
+ @iswrapper
+ # ! [updatemktdepth]
+ def updateMktDepth(self, reqId: TickerId, position: int, operation: int,
+ side: int, price: float, size: Decimal):
+ super().updateMktDepth(reqId, position, operation, side, price, size)
+ print("UpdateMarketDepth. ReqId:", reqId, "Position:", position, "Operation:",
+ operation, "Side:", side, "Price:", floatMaxString(price), "Size:", decimalMaxString(size))
+ # ! [updatemktdepth]
+
+ @iswrapper
+ # ! [updatemktdepthl2]
+ def updateMktDepthL2(self, reqId: TickerId, position: int, marketMaker: str,
+ operation: int, side: int, price: float, size: Decimal, isSmartDepth: bool):
+ super().updateMktDepthL2(reqId, position, marketMaker, operation, side,
+ price, size, isSmartDepth)
+ print("UpdateMarketDepthL2. ReqId:", reqId, "Position:", position, "MarketMaker:", marketMaker, "Operation:",
+ operation, "Side:", side, "Price:", floatMaxString(price), "Size:", decimalMaxString(size), "isSmartDepth:", isSmartDepth)
+
+ # ! [updatemktdepthl2]
+
+ @iswrapper
+ # ! [rerouteMktDepthReq]
+ def rerouteMktDepthReq(self, reqId: int, conId: int, exchange: str):
+ super().rerouteMktDataReq(reqId, conId, exchange)
+ print("Re-route market depth request. ReqId:", reqId, "ConId:", conId, "Exchange:", exchange)
+ # ! [rerouteMktDepthReq]
+
+ @printWhenExecuting
+ def realTimeBarsOperations_req(self):
+ # Requesting real time bars
+ # ! [reqrealtimebars]
+ self.reqRealTimeBars(3001, ContractSamples.EurGbpFx(), 5, "MIDPOINT", True, [])
+ # ! [reqrealtimebars]
+
+ @iswrapper
+ # ! [realtimebar]
+ def realtimeBar(self, reqId: TickerId, time:int, open_: float, high: float, low: float, close: float,
+ volume: Decimal, wap: Decimal, count: int):
+ super().realtimeBar(reqId, time, open_, high, low, close, volume, wap, count)
+ print("RealTimeBar. TickerId:", reqId, RealTimeBar(time, -1, open_, high, low, close, volume, wap, count))
+ # ! [realtimebar]
+
+ @printWhenExecuting
+ def realTimeBarsOperations_cancel(self):
+ # Canceling real time bars
+ # ! [cancelrealtimebars]
+ self.cancelRealTimeBars(3001)
+ # ! [cancelrealtimebars]
+
+ @printWhenExecuting
+ def historicalDataOperations_req(self):
+ # Requesting historical data
+ # ! [reqHeadTimeStamp]
+ self.reqHeadTimeStamp(4101, ContractSamples.USStockAtSmart(), "TRADES", 0, 1)
+ # ! [reqHeadTimeStamp]
+
+ # ! [reqhistoricaldata]
+ queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d-%H:%M:%S")
+ self.reqHistoricalData(4102, ContractSamples.EurGbpFx(), queryTime,
+ "1 M", "1 day", "MIDPOINT", 1, 1, False, [])
+ self.reqHistoricalData(4103, ContractSamples.EuropeanStock(), queryTime,
+ "10 D", "1 min", "TRADES", 1, 1, False, [])
+ self.reqHistoricalData(4104, ContractSamples.EurGbpFx(), "",
+ "1 M", "1 day", "MIDPOINT", 1, 1, True, [])
+ self.reqHistoricalData(4103, ContractSamples.USStockAtSmart(), queryTime,
+ "1 M", "1 day", "SCHEDULE", 1, 1, False, [])
+ # ! [reqhistoricaldata]
+
+ @printWhenExecuting
+ def historicalDataOperations_cancel(self):
+ # ! [cancelHeadTimestamp]
+ self.cancelHeadTimeStamp(4101)
+ # ! [cancelHeadTimestamp]
+
+ # Canceling historical data requests
+ # ! [cancelhistoricaldata]
+ self.cancelHistoricalData(4102)
+ self.cancelHistoricalData(4103)
+ self.cancelHistoricalData(4104)
+ # ! [cancelhistoricaldata]
+
+ @printWhenExecuting
+ def historicalTicksOperations_req(self):
+ # ! [reqhistoricalticks]
+ self.reqHistoricalTicks(18001, ContractSamples.USStockAtSmart(),
+ "20170712 21:39:33 US/Eastern", "", 10, "TRADES", 1, True, [])
+ self.reqHistoricalTicks(18002, ContractSamples.USStockAtSmart(),
+ "20170712 21:39:33 US/Eastern", "", 10, "BID_ASK", 1, True, [])
+ self.reqHistoricalTicks(18003, ContractSamples.USStockAtSmart(),
+ "20170712 21:39:33 US/Eastern", "", 10, "MIDPOINT", 1, True, [])
+ # ! [reqhistoricalticks]
+
+ @printWhenExecuting
+ def historicalTicksOperations_cancel(self):
+ # ! [cancelHistoricalTicks]
+ self.cancelHistoricalTicks(18001)
+ # ! [cancelHistoricalTicks]
+
+ @iswrapper
+ # ! [headTimestamp]
+ def headTimestamp(self, reqId:int, headTimestamp:str):
+ print("HeadTimestamp. ReqId:", reqId, "HeadTimeStamp:", headTimestamp)
+ # ! [headTimestamp]
+
+ @iswrapper
+ # ! [histogramData]
+ def histogramData(self, reqId:int, items:HistogramDataList):
+ print("HistogramData. ReqId:", reqId, "HistogramDataList:", "[%s]" % "; ".join(map(str, items)))
+ # ! [histogramData]
+
+ @iswrapper
+ # ! [historicaldata]
+ def historicalData(self, reqId:int, bar: BarData):
+ print("HistoricalData. ReqId:", reqId, "BarData.", bar)
+ # ! [historicaldata]
+
+ @iswrapper
+ # ! [historicaldataend]
+ def historicalDataEnd(self, reqId: int, start: str, end: str):
+ super().historicalDataEnd(reqId, start, end)
+ print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)
+ # ! [historicaldataend]
+
+ @iswrapper
+ # ! [historicalDataUpdate]
+ def historicalDataUpdate(self, reqId: int, bar: BarData):
+ print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)
+ # ! [historicalDataUpdate]
+
+ @iswrapper
+ # ! [historicalticks]
+ def historicalTicks(self, reqId: int, ticks: ListOfHistoricalTick, done: bool):
+ for tick in ticks:
+ print("HistoricalTick. ReqId:", reqId, tick)
+ # ! [historicalticks]
+
+ @iswrapper
+ # ! [historicalticksbidask]
+ def historicalTicksBidAsk(self, reqId: int, ticks: ListOfHistoricalTickBidAsk,
+ done: bool):
+ for tick in ticks:
+ print("HistoricalTickBidAsk. ReqId:", reqId, tick)
+ # ! [historicalticksbidask]
+
+ @iswrapper
+ # ! [historicaltickslast]
+ def historicalTicksLast(self, reqId: int, ticks: ListOfHistoricalTickLast,
+ done: bool):
+ for tick in ticks:
+ print("HistoricalTickLast. ReqId:", reqId, tick)
+ # ! [historicaltickslast]
+
+ @printWhenExecuting
+ def optionsOperations_req(self):
+ # ! [reqsecdefoptparams]
+ self.reqSecDefOptParams(0, "IBM", "", "STK", 8314)
+ # ! [reqsecdefoptparams]
+
+ # Calculating implied volatility
+ # ! [calculateimpliedvolatility]
+ self.calculateImpliedVolatility(5001, ContractSamples.OptionWithLocalSymbol(), 0.5, 55, [])
+ # ! [calculateimpliedvolatility]
+
+ # Calculating option's price
+ # ! [calculateoptionprice]
+ self.calculateOptionPrice(5002, ContractSamples.OptionWithLocalSymbol(), 0.6, 55, [])
+ # ! [calculateoptionprice]
+
+ # Exercising options
+ # ! [exercise_options]
+ self.exerciseOptions(5003, ContractSamples.OptionWithTradingClass(), 1,
+ 1, self.account, 1, "20231018-12:00:00", "CustAcct", True)
+ # ! [exercise_options]
+
+ @printWhenExecuting
+ def optionsOperations_cancel(self):
+ # Canceling implied volatility
+ self.cancelCalculateImpliedVolatility(5001)
+ # Canceling option's price calculation
+ self.cancelCalculateOptionPrice(5002)
+
+ @iswrapper
+ # ! [securityDefinitionOptionParameter]
+ def securityDefinitionOptionParameter(self, reqId: int, exchange: str,
+ underlyingConId: int, tradingClass: str, multiplier: str,
+ expirations: SetOfString, strikes: SetOfFloat):
+ super().securityDefinitionOptionParameter(reqId, exchange,
+ underlyingConId, tradingClass, multiplier, expirations, strikes)
+ print("SecurityDefinitionOptionParameter.",
+ "ReqId:", reqId, "Exchange:", exchange, "Underlying conId:", intMaxString(underlyingConId), "TradingClass:", tradingClass, "Multiplier:", multiplier,
+ "Expirations:", expirations, "Strikes:", str(strikes))
+ # ! [securityDefinitionOptionParameter]
+
+ @iswrapper
+ # ! [securityDefinitionOptionParameterEnd]
+ def securityDefinitionOptionParameterEnd(self, reqId: int):
+ super().securityDefinitionOptionParameterEnd(reqId)
+ print("SecurityDefinitionOptionParameterEnd. ReqId:", reqId)
+ # ! [securityDefinitionOptionParameterEnd]
+
+ @iswrapper
+ # ! [tickoptioncomputation]
+ def tickOptionComputation(self, reqId: TickerId, tickType: TickType, tickAttrib: int,
+ impliedVol: float, delta: float, optPrice: float, pvDividend: float,
+ gamma: float, vega: float, theta: float, undPrice: float):
+ super().tickOptionComputation(reqId, tickType, tickAttrib, impliedVol, delta,
+ optPrice, pvDividend, gamma, vega, theta, undPrice)
+ print("TickOptionComputation. TickerId:", reqId, "TickType:", tickType,
+ "TickAttrib:", intMaxString(tickAttrib),
+ "ImpliedVolatility:", floatMaxString(impliedVol), "Delta:", floatMaxString(delta), "OptionPrice:",
+ floatMaxString(optPrice), "pvDividend:", floatMaxString(pvDividend), "Gamma: ", floatMaxString(gamma), "Vega:", floatMaxString(vega),
+ "Theta:", floatMaxString(theta), "UnderlyingPrice:", floatMaxString(undPrice))
+
+ # ! [tickoptioncomputation]
+
+
+ @printWhenExecuting
+ def contractOperations_req(self):
+ # ! [reqcontractdetails]
+ self.reqContractDetails(210, ContractSamples.OptionForQuery())
+ self.reqContractDetails(211, ContractSamples.EurGbpFx())
+ self.reqContractDetails(212, ContractSamples.Bond())
+ self.reqContractDetails(213, ContractSamples.FuturesOnOptions())
+ self.reqContractDetails(214, ContractSamples.SimpleFuture())
+ self.reqContractDetails(215, ContractSamples.USStockAtSmart())
+ self.reqContractDetails(216, ContractSamples.CryptoContract())
+ self.reqContractDetails(217, ContractSamples.ByIssuerId())
+ self.reqContractDetails(219, ContractSamples.FundContract())
+ self.reqContractDetails(220, ContractSamples.USStock())
+ self.reqContractDetails(221, ContractSamples.USStockAtSmart())
+ self.reqContractDetails(220, ContractSamples.OptForecastx())
+ self.reqContractDetails(221, ContractSamples.OptForecastxZeroStrike())
+ self.reqContractDetails(222, ContractSamples.OptForecastxByConId())
+ # ! [reqcontractdetails]
+
+ # ! [reqmatchingsymbols]
+ self.reqMatchingSymbols(218, "IBM")
+ # ! [reqmatchingsymbols]
+
+ @printWhenExecuting
+ def contractOperations_cancel(self):
+ # ! [cancelContractData]
+ self.cancelContractData(210)
+ # ! [cancelContractData]
+
+ @printWhenExecuting
+ def newsOperations_req(self):
+ # Requesting news ticks
+ # ! [reqNewsTicks]
+ self.reqMktData(10001, ContractSamples.USStockAtSmart(), "mdoff,292", False, False, [])
+ # ! [reqNewsTicks]
+
+ # Returns list of subscribed news providers
+ # ! [reqNewsProviders]
+ self.reqNewsProviders()
+ # ! [reqNewsProviders]
+
+ # Returns body of news article given article ID
+ # ! [reqNewsArticle]
+ self.reqNewsArticle(10002,"BRFG", "BRFG$04fb9da2", [])
+ # ! [reqNewsArticle]
+
+ # Returns list of historical news headlines with IDs
+ # ! [reqHistoricalNews]
+ self.reqHistoricalNews(10003, 8314, "BRFG", "", "", 10, [])
+ # ! [reqHistoricalNews]
+
+ # ! [reqcontractdetailsnews]
+ self.reqContractDetails(10004, ContractSamples.NewsFeedForQuery())
+ # ! [reqcontractdetailsnews]
+
+ @printWhenExecuting
+ def newsOperations_cancel(self):
+ # Canceling news ticks
+ # ! [cancelNewsTicks]
+ self.cancelMktData(10001)
+ # ! [cancelNewsTicks]
+
+ @iswrapper
+ #! [tickNews]
+ def tickNews(self, tickerId: int, timeStamp: int, providerCode: str,
+ articleId: str, headline: str, extraData: str):
+ print("TickNews. TickerId:", tickerId, "TimeStamp:", intMaxString(timeStamp),
+ "ProviderCode:", providerCode, "ArticleId:", articleId,
+ "Headline:", headline, "ExtraData:", extraData)
+ #! [tickNews]
+
+ @iswrapper
+ #! [historicalNews]
+ def historicalNews(self, reqId: int, time: str, providerCode: str,
+ articleId: str, headline: str):
+ print("HistoricalNews. ReqId:", reqId, "Time:", time,
+ "ProviderCode:", providerCode, "ArticleId:", articleId,
+ "Headline:", headline)
+ #! [historicalNews]
+
+ @iswrapper
+ #! [historicalNewsEnd]
+ def historicalNewsEnd(self, reqId:int, hasMore:bool):
+ print("HistoricalNewsEnd. ReqId:", reqId, "HasMore:", hasMore)
+ #! [historicalNewsEnd]
+
+ @iswrapper
+ #! [newsProviders]
+ def newsProviders(self, newsProviders: ListOfNewsProviders):
+ print("NewsProviders: ")
+ for provider in newsProviders:
+ print("NewsProvider.", provider)
+ #! [newsProviders]
+
+ @iswrapper
+ #! [newsArticle]
+ def newsArticle(self, reqId: int, articleType: int, articleText: str):
+ print("NewsArticle. ReqId:", reqId, "ArticleType:", articleType,
+ "ArticleText:", articleText)
+ #! [newsArticle]
+
+ @iswrapper
+ # ! [contractdetails]
+ def contractDetails(self, reqId: int, contractDetails: ContractDetails):
+ super().contractDetails(reqId, contractDetails)
+ printinstance(contractDetails)
+ # ! [contractdetails]
+
+ @iswrapper
+ # ! [bondcontractdetails]
+ def bondContractDetails(self, reqId: int, contractDetails: ContractDetails):
+ super().bondContractDetails(reqId, contractDetails)
+ printinstance(contractDetails)
+ # ! [bondcontractdetails]
+
+ @iswrapper
+ # ! [contractdetailsend]
+ def contractDetailsEnd(self, reqId: int):
+ super().contractDetailsEnd(reqId)
+ print("ContractDetailsEnd. ReqId:", reqId)
+ # ! [contractdetailsend]
+
+ @iswrapper
+ # ! [symbolSamples]
+ def symbolSamples(self, reqId: int,
+ contractDescriptions: ListOfContractDescription):
+ super().symbolSamples(reqId, contractDescriptions)
+ print("Symbol Samples. Request Id: ", reqId)
+
+ for contractDescription in contractDescriptions:
+ derivSecTypes = ""
+ for derivSecType in contractDescription.derivativeSecTypes:
+ derivSecTypes += " "
+ derivSecTypes += derivSecType
+ print("Contract: conId:%s, symbol:%s, secType:%s, primExchange:%s, "
+ "currency:%s, derivativeSecTypes:%s, description:%s, issuerId:%s" % (
+ contractDescription.contract.conId,
+ contractDescription.contract.symbol,
+ contractDescription.contract.secType,
+ contractDescription.contract.primaryExchange,
+ contractDescription.contract.currency, derivSecTypes,
+ contractDescription.contract.description,
+ contractDescription.contract.issuerId))
+ # ! [symbolSamples]
+
+ @printWhenExecuting
+ def marketScannersOperations_req(self):
+ # Requesting list of valid scanner parameters which can be used in TWS
+ # ! [reqscannerparameters]
+ self.reqScannerParameters()
+ # ! [reqscannerparameters]
+
+ # Triggering a scanner subscription
+ # ! [reqscannersubscription]
+ self.reqScannerSubscription(7001, ScannerSubscriptionSamples.HighOptVolumePCRatioUSIndexes(), [], [])
+
+ # Generic Filters
+ tagvalues = []
+ tagvalues.append(TagValue("usdMarketCapAbove", "10000"))
+ tagvalues.append(TagValue("optVolumeAbove", "1000"))
+ tagvalues.append(TagValue("avgVolumeAbove", "10000"))
+
+ self.reqScannerSubscription(7002, ScannerSubscriptionSamples.HotUSStkByVolume(), [], tagvalues) # requires TWS v973+
+ # ! [reqscannersubscription]
+
+ # ! [reqcomplexscanner]
+ AAPLConIDTag = [TagValue("underConID", "265598")]
+ self.reqScannerSubscription(7003, ScannerSubscriptionSamples.ComplexOrdersAndTrades(), [], AAPLConIDTag) # requires TWS v975+
+
+ # ! [reqcomplexscanner]
+
+
+ @printWhenExecuting
+ def marketScanners_cancel(self):
+ # Canceling the scanner subscription
+ # ! [cancelscannersubscription]
+ self.cancelScannerSubscription(7001)
+ self.cancelScannerSubscription(7002)
+ self.cancelScannerSubscription(7003)
+ # ! [cancelscannersubscription]
+
+ @iswrapper
+ # ! [scannerparameters]
+ def scannerParameters(self, xml: str):
+ super().scannerParameters(xml)
+ open('log/scanner.xml', 'w').write(xml)
+ print("ScannerParameters received.")
+ # ! [scannerparameters]
+
+ @iswrapper
+ # ! [scannerdata]
+ def scannerData(self, reqId: int, rank: int, contractDetails: ContractDetails,
+ distance: str, benchmark: str, projection: str, legsStr: str):
+ super().scannerData(reqId, rank, contractDetails, distance, benchmark,
+ projection, legsStr)
+# print("ScannerData. ReqId:", reqId, "Rank:", rank, "Symbol:", contractDetails.contract.symbol,
+# "SecType:", contractDetails.contract.secType,
+# "Currency:", contractDetails.contract.currency,
+# "Distance:", distance, "Benchmark:", benchmark,
+# "Projection:", projection, "Legs String:", legsStr)
+ print("ScannerData. ReqId:", reqId, ScanData(contractDetails.contract, rank, distance, benchmark, projection, legsStr, contractDetails.marketName))
+ # ! [scannerdata]
+
+ @iswrapper
+ # ! [scannerdataend]
+ def scannerDataEnd(self, reqId: int):
+ super().scannerDataEnd(reqId)
+ print("ScannerDataEnd. ReqId:", reqId)
+ # ! [scannerdataend]
+
+ @iswrapper
+ # ! [smartcomponents]
+ def smartComponents(self, reqId:int, smartComponentMap:SmartComponentMap):
+ super().smartComponents(reqId, smartComponentMap)
+ print(f"SmartComponents - ReqId: {reqId}")
+ for bitNumber, (exchange, exchangeLetter) in smartComponentMap.items():
+ print(f" BitNumber: {bitNumber}, Exchange: '{exchange}', ExchangeLetter: '{exchangeLetter}'")
+ # ! [smartcomponents]
+
+ @iswrapper
+ # ! [tickReqParams]
+ def tickReqParams(self, tickerId:int, minTick:float,
+ bboExchange:str, snapshotPermissions:int):
+ super().tickReqParams(tickerId, minTick, bboExchange, snapshotPermissions)
+ # ! [tickReqParams]
+
+ @iswrapper
+ # ! [mktDepthExchanges]
+ def mktDepthExchanges(self, depthMktDataDescriptions:ListOfDepthExchanges):
+ super().mktDepthExchanges(depthMktDataDescriptions)
+ print("MktDepthExchanges:")
+ for desc in depthMktDataDescriptions:
+ print("DepthMktDataDescription.", desc)
+ # ! [mktDepthExchanges]
+
+ @printWhenExecuting
+ def fundamentalsOperations_req(self):
+ # Requesting Fundamentals
+ # ! [reqfundamentaldata]
+ self.reqFundamentalData(8001, ContractSamples.USStock(), "ReportsFinSummary", [])
+ # ! [reqfundamentaldata]
+
+ # ! [fundamentalexamples]
+ self.reqFundamentalData(8002, ContractSamples.USStock(), "ReportSnapshot", []) # for company overview
+ self.reqFundamentalData(8003, ContractSamples.USStock(), "ReportRatios", []) # for financial ratios
+ self.reqFundamentalData(8004, ContractSamples.USStock(), "ReportsFinStatements", []) # for financial statements
+ self.reqFundamentalData(8005, ContractSamples.USStock(), "RESC", []) # for analyst estimates
+ self.reqFundamentalData(8006, ContractSamples.USStock(), "CalendarReport", []) # for company calendar
+ # ! [fundamentalexamples]
+
+ @printWhenExecuting
+ def fundamentalsOperations_cancel(self):
+ # Canceling fundamentalsOperations_req request
+ # ! [cancelfundamentaldata]
+ self.cancelFundamentalData(8001)
+ # ! [cancelfundamentaldata]
+
+ # ! [cancelfundamentalexamples]
+ self.cancelFundamentalData(8002)
+ self.cancelFundamentalData(8003)
+ self.cancelFundamentalData(8004)
+ self.cancelFundamentalData(8005)
+ self.cancelFundamentalData(8006)
+ # ! [cancelfundamentalexamples]
+
+ @iswrapper
+ # ! [fundamentaldata]
+ def fundamentalData(self, reqId: TickerId, data: str):
+ super().fundamentalData(reqId, data)
+ print("FundamentalData. ReqId:", reqId, "Data:", data)
+ # ! [fundamentaldata]
+
+ @printWhenExecuting
+ def bulletinsOperations_req(self):
+ # Requesting Interactive Broker's news bulletinsOperations_req
+ # ! [reqnewsbulletins]
+ self.reqNewsBulletins(True)
+ # ! [reqnewsbulletins]
+
+ @printWhenExecuting
+ def bulletinsOperations_cancel(self):
+ # Canceling IB's news bulletinsOperations_req
+ # ! [cancelnewsbulletins]
+ self.cancelNewsBulletins()
+ # ! [cancelnewsbulletins]
+
+ @iswrapper
+ # ! [updatenewsbulletin]
+ def updateNewsBulletin(self, msgId: int, msgType: int, newsMessage: str,
+ originExch: str):
+ super().updateNewsBulletin(msgId, msgType, newsMessage, originExch)
+ print("News Bulletins. MsgId:", msgId, "Type:", msgType, "Message:", newsMessage,
+ "Exchange of Origin: ", originExch)
+ # ! [updatenewsbulletin]
+
+ def ocaSample(self):
+ # OCA ORDER
+ # ! [ocasubmit]
+ ocaOrders = [OrderSamples.LimitOrder("BUY", 1, 10), OrderSamples.LimitOrder("BUY", 1, 11),
+ OrderSamples.LimitOrder("BUY", 1, 12)]
+ OrderSamples.OneCancelsAll("TestOCA_" + str(self.nextValidOrderId), ocaOrders, 2)
+ for o in ocaOrders:
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), o)
+ # ! [ocasubmit]
+
+ def conditionSamples(self):
+ # ! [order_conditioning_activate]
+ mkt = OrderSamples.MarketOrder("BUY", 100)
+ # Order will become active if conditioning criteria is met
+ mkt.conditions.append(
+ OrderSamples.PriceCondition(PriceCondition.TriggerMethodEnum.Default,
+ 208813720, "SMART", 600, False, False))
+ mkt.conditions.append(OrderSamples.ExecutionCondition("EUR.USD", "CASH", "IDEALPRO", True))
+ mkt.conditions.append(OrderSamples.MarginCondition(30, True, False))
+ mkt.conditions.append(OrderSamples.PercentageChangeCondition(15.0, 208813720, "SMART", True, True))
+ mkt.conditions.append(OrderSamples.TimeCondition("20160118 23:59:59 US/Eastern", True, False))
+ mkt.conditions.append(OrderSamples.VolumeCondition(208813720, "SMART", False, 100, True))
+ self.placeOrder(self.nextOrderId(), ContractSamples.EuropeanStock(), mkt)
+ # ! [order_conditioning_activate]
+
+ # Conditions can make the order active or cancel it. Only LMT orders can be conditionally canceled.
+ # ! [order_conditioning_cancel]
+ lmt = OrderSamples.LimitOrder("BUY", 100, 20)
+ # The active order will be cancelled if conditioning criteria is met
+ lmt.conditionsCancelOrder = True
+ lmt.conditions.append(
+ OrderSamples.PriceCondition(PriceCondition.TriggerMethodEnum.Last,
+ 208813720, "SMART", 600, False, False))
+ self.placeOrder(self.nextOrderId(), ContractSamples.EuropeanStock(), lmt)
+ # ! [order_conditioning_cancel]
+
+ def bracketSample(self):
+ # BRACKET ORDER
+ # ! [bracketsubmit]
+ bracket = OrderSamples.BracketOrder(self.nextOrderId(), "BUY", 100, 30, 40, 20)
+ for o in bracket:
+ self.placeOrder(o.orderId, ContractSamples.EuropeanStock(), o)
+ self.nextOrderId() # need to advance this we'll skip one extra oid, it's fine
+ # ! [bracketsubmit]
+
+ def hedgeSample(self):
+ # F Hedge order
+ # ! [hedgesubmit]
+ # Parent order on a contract which currency differs from your base currency
+ parent = OrderSamples.LimitOrder("BUY", 100, 10)
+ parent.orderId = self.nextOrderId()
+ parent.transmit = False
+ # Hedge on the currency conversion
+ hedge = OrderSamples.MarketFHedge(parent.orderId, "BUY")
+ # Place the parent first...
+ self.placeOrder(parent.orderId, ContractSamples.EuropeanStock(), parent)
+ # Then the hedge order
+ self.placeOrder(self.nextOrderId(), ContractSamples.EurGbpFx(), hedge)
+ # ! [hedgesubmit]
+
+ def algoSamples(self):
+ # ! [scale_order]
+ scaleOrder = OrderSamples.RelativePeggedToPrimary("BUY", 70000, 189, 0.01)
+ AvailableAlgoParams.FillScaleParams(scaleOrder, 2000, 500, True, .02, 189.00, 3600, 2.00, True, 10, 40)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), scaleOrder)
+ # ! [scale_order]
+
+ time.sleep(1)
+
+ # ! [algo_base_order]
+ baseOrder = OrderSamples.LimitOrder("BUY", 1000, 1)
+ # ! [algo_base_order]
+
+ # ! [arrivalpx]
+ AvailableAlgoParams.FillArrivalPriceParams(baseOrder, 0.1, "Aggressive", "09:00:00 US/Eastern", "16:00:00 US/Eastern", True, True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [arrivalpx]
+
+ # ! [darkice]
+ AvailableAlgoParams.FillDarkIceParams(baseOrder, 10, "09:00:00 US/Eastern", "16:00:00 US/Eastern", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [darkice]
+
+ # ! [place_midprice]
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), OrderSamples.Midprice("BUY", 1, 150))
+ # ! [place_midprice]
+
+ # ! [ad]
+ # The Time Zone in "startTime" and "endTime" attributes is ignored and always defaulted to GMT
+ AvailableAlgoParams.FillAccumulateDistributeParams(baseOrder, 10, 60, True, True, 1, True, True, "12:00:00", "16:00:00")
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [ad]
+
+ # ! [twap]
+ AvailableAlgoParams.FillTwapParams(baseOrder, "Marketable", "09:00:00 US/Eastern", "16:00:00 US/Eastern", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [twap]
+
+ # ! [vwap]
+ AvailableAlgoParams.FillVwapParams(baseOrder, 0.2, "09:00:00 US/Eastern", "16:00:00 US/Eastern", True, True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [vwap]
+
+ # ! [balanceimpactrisk]
+ AvailableAlgoParams.FillBalanceImpactRiskParams(baseOrder, 0.1, "Aggressive", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USOptionContract(), baseOrder)
+ # ! [balanceimpactrisk]
+
+ # ! [minimpact]
+ AvailableAlgoParams.FillMinImpactParams(baseOrder, 0.3)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USOptionContract(), baseOrder)
+ # ! [minimpact]
+
+ # ! [adaptive]
+ AvailableAlgoParams.FillAdaptiveParams(baseOrder, "Normal")
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [adaptive]
+
+ # ! [closepx]
+ AvailableAlgoParams.FillClosePriceParams(baseOrder, 0.4, "Neutral", "20180926-06:06:49", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [closepx]
+
+ # ! [pctvol]
+ AvailableAlgoParams.FillPctVolParams(baseOrder, 0.5, "12:00:00 US/Eastern", "14:00:00 US/Eastern", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [pctvol]
+
+ # ! [pctvolpx]
+ AvailableAlgoParams.FillPriceVariantPctVolParams(baseOrder, 0.1, 0.05, 0.01, 0.2, "12:00:00 US/Eastern", "14:00:00 US/Eastern", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [pctvolpx]
+
+ # ! [pctvolsz]
+ AvailableAlgoParams.FillSizeVariantPctVolParams(baseOrder, 0.2, 0.4, "12:00:00 US/Eastern", "14:00:00 US/Eastern", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [pctvolsz]
+
+ # ! [pctvoltm]
+ AvailableAlgoParams.FillTimeVariantPctVolParams(baseOrder, 0.2, 0.4, "12:00:00 US/Eastern", "14:00:00 US/Eastern", True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), baseOrder)
+ # ! [pctvoltm]
+
+ # ! [jeff_vwap_algo]
+ AvailableAlgoParams.FillJefferiesVWAPParams(baseOrder, "10:00:00 US/Eastern", "16:00:00 US/Eastern", 10, 10, "Exclude_Both", 130, 135, 1, 10, "Patience", False, "Midpoint")
+ self.placeOrder(self.nextOrderId(), ContractSamples.JefferiesContract(), baseOrder)
+ # ! [jeff_vwap_algo]
+
+ # ! [csfb_inline_algo]
+ AvailableAlgoParams.FillCSFBInlineParams(baseOrder, "10:00:00 US/Eastern", "16:00:00 US/Eastern", "Patient", 10, 20, 100, "Default", False, 40, 100, 100, 35)
+ self.placeOrder(self.nextOrderId(), ContractSamples.CSFBContract(), baseOrder)
+ # ! [csfb_inline_algo]
+
+ # ! [qbalgo_strobe_algo]
+ AvailableAlgoParams.FillQBAlgoInLineParams(baseOrder, "10:00:00 US/Eastern", "16:00:00 US/Eastern", -99, "TWAP", 0.25, True)
+ self.placeOrder(self.nextOrderId(), ContractSamples.QBAlgoContract(), baseOrder)
+ # ! [qbalgo_strobe_algo]
+
+ @printWhenExecuting
+ def financialAdvisorOperations(self):
+ # Requesting FA information
+ # ! [requestfaaliases]
+ self.requestFA(FaDataTypeEnum.ALIASES)
+ # ! [requestfaaliases]
+
+ # ! [requestfagroups]
+ self.requestFA(FaDataTypeEnum.GROUPS)
+ # ! [requestfagroups]
+
+ # Replacing FA information - Fill in with the appropriate XML string.
+ # ! [replacefaupdatedgroup]
+ self.replaceFA(1000, FaDataTypeEnum.GROUPS, FaAllocationSamples.FaUpdatedGroup)
+ # ! [replacefaupdatedgroup]
+
+ # ! [reqSoftDollarTiers]
+ self.reqSoftDollarTiers(14001)
+ # ! [reqSoftDollarTiers]
+
+ def wshCalendarOperations(self):
+ # ! [reqmetadata]
+ self.reqWshMetaData(1100)
+ # ! [reqmetadata]
+
+ # ! [reqeventdata]
+ wshEventData1 = WshEventData()
+ wshEventData1.conId = 8314
+ wshEventData1.startDate = "20220511"
+ wshEventData1.totalLimit = 5
+ self.reqWshEventData(1101, wshEventData1)
+ # ! [reqeventdata]
+
+ # ! [reqeventdata]
+ wshEventData2 = WshEventData()
+ wshEventData2.filter = "{\"watchlist\":[\"8314\"]}"
+ wshEventData2.fillWatchlist = False
+ wshEventData2.fillPortfolio = False
+ wshEventData2.fillCompetitors = False
+ wshEventData2.endDate = "20220512"
+ self.reqWshEventData(1102, wshEventData2)
+ # ! [reqeventdata]
+
+ @iswrapper
+ # ! [receivefa]
+ def receiveFA(self, faData: FaDataType, cxml: str):
+ super().receiveFA(faData, cxml)
+ print("Receiving FA: ", faData)
+ open('log/fa.xml', 'w').write(cxml)
+ # ! [receivefa]
+
+ @iswrapper
+ # ! [softDollarTiers]
+ def softDollarTiers(self, reqId: int, tiers: list):
+ super().softDollarTiers(reqId, tiers)
+ print("SoftDollarTiers. ReqId:", reqId)
+ for tier in tiers:
+ print("SoftDollarTier.", tier)
+ # ! [softDollarTiers]
+
+ @printWhenExecuting
+ def miscelaneousOperations(self):
+ # Request TWS' current time
+ self.reqCurrentTime()
+ # Setting TWS logging level
+ self.setServerLogLevel(1)
+ time.sleep(3)
+ # Request TWS' current time in millis
+ self.reqCurrentTimeInMillis()
+
+ @printWhenExecuting
+ def linkingOperations(self):
+ # ! [querydisplaygroups]
+ self.queryDisplayGroups(19001)
+ # ! [querydisplaygroups]
+
+ # ! [subscribetogroupevents]
+ self.subscribeToGroupEvents(19002, 1)
+ # ! [subscribetogroupevents]
+
+ # ! [updatedisplaygroup]
+ self.updateDisplayGroup(19002, "8314@SMART")
+ # ! [updatedisplaygroup]
+
+ # ! [subscribefromgroupevents]
+ self.unsubscribeFromGroupEvents(19002)
+ # ! [subscribefromgroupevents]
+
+ @iswrapper
+ # ! [displaygrouplist]
+ def displayGroupList(self, reqId: int, groups: str):
+ super().displayGroupList(reqId, groups)
+ print("DisplayGroupList. ReqId:", reqId, "Groups", groups)
+ # ! [displaygrouplist]
+
+ @iswrapper
+ # ! [displaygroupupdated]
+ def displayGroupUpdated(self, reqId: int, contractInfo: str):
+ super().displayGroupUpdated(reqId, contractInfo)
+ print("DisplayGroupUpdated. ReqId:", reqId, "ContractInfo:", contractInfo)
+ # ! [displaygroupupdated]
+
+ @printWhenExecuting
+ def whatIfOrderOperations(self):
+ # ! [whatiflimitorder]
+ whatIfOrder = OrderSamples.LimitOrder("BUY", 100, 20)
+ whatIfOrder.whatIf = True
+ whatIfOrder.tif = "DAY"
+ self.placeOrder(self.nextOrderId(), ContractSamples.BondWithCusip(), whatIfOrder)
+ # ! [whatiflimitorder]
+ time.sleep(2)
+
+ @printWhenExecuting
+ def orderOperations_req(self):
+ # Requesting the next valid id
+ # ! [reqids]
+ # The parameter is always ignored.
+ self.reqIds(-1)
+ # ! [reqids]
+
+ # Requesting all open orders
+ # ! [reqallopenorders]
+ self.reqAllOpenOrders()
+ # ! [reqallopenorders]
+
+ # Taking over orders to be submitted via TWS
+ # ! [reqautoopenorders]
+ self.reqAutoOpenOrders(True)
+ # ! [reqautoopenorders]
+
+ # Requesting this API client's orders
+ # ! [reqopenorders]
+ self.reqOpenOrders()
+ # ! [reqopenorders]
+
+ # Placing/modifying an order - remember to ALWAYS increment the
+ # nextValidId after placing an order so it can be used for the next one!
+ # Note if there are multiple clients connected to an account, the
+ # order ID must also be greater than all order IDs returned for orders
+ # to orderStatus and openOrder to this client.
+
+ # ! [order_submission]
+ self.simplePlaceOid = self.nextOrderId()
+ self.placeOrder(self.simplePlaceOid, ContractSamples.USStock(),
+ OrderSamples.LimitOrder("SELL", 1, 50))
+ # ! [order_submission]
+
+ # ! [faorderoneaccount]
+ faOrderOneAccount = OrderSamples.MarketOrder("BUY", 100)
+ # Specify the Account Number directly
+ faOrderOneAccount.account = "DU119915"
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(), faOrderOneAccount)
+ # ! [faorderoneaccount]
+
+ # ! [faordergroup]
+ faOrderGroup = OrderSamples.LimitOrder("BUY", 200, 10)
+ faOrderGroup.faGroup = "MyTestGroup1"
+ faOrderGroup.faMethod = "AvailableEquity"
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), faOrderGroup)
+ # ! [faordergroup]
+
+ # ! [faorderuserdefinedgroup]
+ faOrderUserDefinedGroup = OrderSamples.LimitOrder("BUY", 200, 10)
+ faOrderUserDefinedGroup.faGroup = "MyTestProfile1"
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), faOrderUserDefinedGroup)
+ # ! [faorderuserdefinedgroup]
+
+ # ! [modelorder]
+ modelOrder = OrderSamples.LimitOrder("BUY", 200, 100)
+ modelOrder.account = "DF12345"
+ modelOrder.modelCode = "Technology" # model for tech stocks first created in TWS
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(), modelOrder)
+ # ! [modelorder]
+
+ self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtBOX(),
+ OrderSamples.Block("BUY", 50, 20))
+ self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtBOX(),
+ OrderSamples.BoxTop("SELL", 10))
+ self.placeOrder(self.nextOrderId(), ContractSamples.FutureComboContract(),
+ OrderSamples.ComboLimitOrder("SELL", 1, 1, False))
+ self.placeOrder(self.nextOrderId(), ContractSamples.StockComboContract(),
+ OrderSamples.ComboMarketOrder("BUY", 1, True))
+ self.placeOrder(self.nextOrderId(), ContractSamples.OptionComboContract(),
+ OrderSamples.ComboMarketOrder("BUY", 1, False))
+ self.placeOrder(self.nextOrderId(), ContractSamples.StockComboContract(),
+ OrderSamples.LimitOrderForComboWithLegPrices("BUY", 1, [10, 5], True))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.Discretionary("SELL", 1, 45, 0.5))
+ self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtBOX(),
+ OrderSamples.LimitIfTouched("BUY", 1, 30, 34))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.LimitOnClose("SELL", 1, 34))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.LimitOnOpen("BUY", 1, 35))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.MarketIfTouched("BUY", 1, 30))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.MarketOnClose("SELL", 1))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.MarketOnOpen("BUY", 1))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.MarketOrder("SELL", 1))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.MarketToLimit("BUY", 1))
+ self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtIse(),
+ OrderSamples.MidpointMatch("BUY", 1))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.MarketToLimit("BUY", 1))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.Stop("SELL", 1, 34.4))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.StopLimit("BUY", 1, 35, 33))
+ self.placeOrder(self.nextOrderId(), ContractSamples.SimpleFuture(),
+ OrderSamples.StopWithProtection("SELL", 1, 45))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.SweepToFill("BUY", 1, 35))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.TrailingStop("SELL", 1, 0.5, 30))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ OrderSamples.TrailingStopLimit("BUY", 1, 2, 5, 50))
+ self.placeOrder(self.nextOrderId(), ContractSamples.USOptionContract(),
+ OrderSamples.Volatility("SELL", 1, 5, 2))
+
+ self.bracketSample()
+
+ self.conditionSamples()
+
+ self.hedgeSample()
+
+ # NOTE: the following orders are not supported for Paper Trading
+ # self.placeOrder(self.nextOrderId(), ContractSamples.USStock(), OrderSamples.AtAuction("BUY", 100, 30.0))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtBOX(), OrderSamples.AuctionLimit("SELL", 10, 30.0, 2))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtBOX(), OrderSamples.AuctionPeggedToStock("BUY", 10, 30, 0.5))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.OptionAtBOX(), OrderSamples.AuctionRelative("SELL", 10, 0.6))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.SimpleFuture(), OrderSamples.MarketWithProtection("BUY", 1))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.USStock(), OrderSamples.PassiveRelative("BUY", 1, 0.5))
+
+ # 208813720 (GOOG)
+ # self.placeOrder(self.nextOrderId(), ContractSamples.USStock(),
+ # OrderSamples.PeggedToBenchmark("SELL", 100, 33, True, 0.1, 1, 208813720, "ARCA", 750, 650, 800))
+
+ # STOP ADJUSTABLE ORDERS
+ # Order stpParent = OrderSamples.Stop("SELL", 100, 30)
+ # stpParent.OrderId = self.nextOrderId()
+ # self.placeOrder(stpParent.OrderId, ContractSamples.EuropeanStock(), stpParent)
+ # self.placeOrder(self.nextOrderId(), ContractSamples.EuropeanStock(), OrderSamples.AttachAdjustableToStop(stpParent, 35, 32, 33))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.EuropeanStock(), OrderSamples.AttachAdjustableToStopLimit(stpParent, 35, 33, 32, 33))
+ # self.placeOrder(self.nextOrderId(), ContractSamples.EuropeanStock(), OrderSamples.AttachAdjustableToTrail(stpParent, 35, 32, 32, 1, 0))
+
+ # Order lmtParent = OrderSamples.LimitOrder("BUY", 100, 30)
+ # lmtParent.OrderId = self.nextOrderId()
+ # self.placeOrder(lmtParent.OrderId, ContractSamples.EuropeanStock(), lmtParent)
+ # Attached TRAIL adjusted can only be attached to LMT parent orders.
+ # self.placeOrder(self.nextOrderId(), ContractSamples.EuropeanStock(), OrderSamples.AttachAdjustableToTrailAmount(lmtParent, 34, 32, 33, 0.008))
+ self.algoSamples()
+
+ self.ocaSample()
+
+ # Request the day's executions
+ # ! [reqexecutions]
+ executionFilter1 = ExecutionFilter()
+ executionFilter1.lastNDays = 7
+ self.reqExecutions(10001, executionFilter1)
+ executionFilter2 = ExecutionFilter()
+ executionFilter2.specificDates = {20250312, 20250306};
+ self.reqExecutions(10002, executionFilter2)
+ # # ! [reqexecutions]
+
+ # ! [reqexecutions_protobuf]
+ executionFilterProto1 = ExecutionFilterProto()
+ executionFilterProto1.lastNDays = 7
+ executionRequestProto1 = ExecutionRequestProto()
+ executionRequestProto1.reqId = 10003
+ executionRequestProto1.executionFilter.CopyFrom(executionFilterProto1)
+ self.reqExecutionsProtoBuf(executionRequestProto1)
+ executionFilterProto2 = ExecutionFilterProto()
+ executionFilterProto2.specificDates.extend({20250512, 20250513, 20250514})
+ executionRequestProto2 = ExecutionRequestProto()
+ executionRequestProto2.reqId = 10004
+ executionRequestProto2.executionFilter.CopyFrom(executionFilterProto2)
+ self.reqExecutionsProtoBuf(executionRequestProto2)
+ # ! [reqexecutions_protobuf]
+
+ # Requesting completed orders
+ # ! [reqcompletedorders]
+ self.reqCompletedOrders(False)
+ # ! [reqcompletedorders]
+
+ # Placing crypto order
+ # ! [cryptoplaceorder]
+ self.placeOrder(self.nextOrderId(), ContractSamples.CryptoContract(), OrderSamples.LimitOrder("BUY", Decimal("0.00001234"), 3370))
+ # ! [cryptoplaceorder]
+
+
+ # Placing limit order with manual order time
+ # ! [place_order_with_manual_order_time]
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), OrderSamples.LimitOrderWithManualOrderTime("BUY", Decimal("100"), 111.11, "20220314-13:00:00"))
+ # ! [place_order_with_manual_order_time]
+
+ # Placing peg best up to mid order
+ # ! [place_peg_best_up_to_mid_order]
+ self.placeOrder(self.nextOrderId(), ContractSamples.IBKRATSContract(), OrderSamples.PegBestUpToMidOrder("BUY", Decimal("100"), 111.11, 100, 200, 0.02, 0.025))
+ # ! [place_peg_best_up_to_mid_order]
+
+ # Placing peg best order
+ # ! [place_peg_best_order]
+ self.placeOrder(self.nextOrderId(), ContractSamples.IBKRATSContract(), OrderSamples.PegBestOrder("BUY", Decimal("100"), 111.11, 100, 200, 0.03))
+ # ! [place_peg_best_order]
+
+ # Placing peg mid order
+ # ! [place_peg_mid_order]
+ self.placeOrder(self.nextOrderId(), ContractSamples.IBKRATSContract(), OrderSamples.PegMidOrder("BUY", Decimal("100"), 111.11, 100, 0.02, 0.025))
+ # ! [place_peg_mid_order]
+
+ # Placing limit order with customer accounte
+ # ! [place_order_with_customer_account]
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), OrderSamples.LimitOrderWithCustomerAccount("BUY", Decimal("100"), 111.11, "CustAcct"))
+ # ! [place_order_with_customer_account]
+
+ # Placing limit order with include overnight
+ # ! [place_order_with_include_overnight]
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), OrderSamples.LimitOrderWithIncludeOvernight("BUY", Decimal("100"), 111.11))
+ # ! [place_order_with_include_overnight]
+
+ # Placing limit order with CME tagging fields
+ # ! [cme_tagging_fields]
+ self.simplePlaceOid = self.nextOrderId()
+ self.placeOrder(self.simplePlaceOid, ContractSamples.SimpleFuture(), OrderSamples.LimitOrderWithCmeTaggingFields("BUY", Decimal("1"), 5333, "ABCD", 1))
+ time.sleep(5)
+ if self.simplePlaceOid is not None:
+ self.cancelOrder(self.simplePlaceOid, OrderSamples.OrderCancelWithCmeTaggingFields("BCDE", 0));
+ time.sleep(2)
+ self.simplePlaceOid = self.nextOrderId()
+ self.placeOrder(self.simplePlaceOid, ContractSamples.SimpleFuture(), OrderSamples.LimitOrderWithCmeTaggingFields("BUY", Decimal("1"), 5444, "CDEF", 0))
+ time.sleep(5)
+ self.reqGlobalCancel(OrderSamples.OrderCancelWithCmeTaggingFields("DEFG", 1))
+ # ! [cme_tagging_fields]
+ #
+ # # Placing limit on close order with imbalance only
+ # # ! [place_order_with_imbalance_only]
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), OrderSamples.LimitOnCloseOrderWithImbalanceOnly("BUY", Decimal("100"), 44.44))
+ # # ! [place_order_with_imbalance_only]
+
+ # ! [zero_strike_opt_order]
+ self.placeOrder(self.nextOrderId(), ContractSamples.OptForecastxZeroStrike(), OrderSamples.LimitOrder("BUY", Decimal("1"), 0.05));
+ # ! [zero_strike_opt_order]
+
+ # ! [limit_order_with_stop_loss_and_profit_taker]
+ self.placeOrder(self.nextOrderId(), ContractSamples.USStockAtSmart(), OrderSamples.LimitOrderWithStopLossAndProfitTaker("BUY", Decimal("100"), 40, self.nextOrderId(), self.nextOrderId()));
+ # ! [limit_order_with_stop_loss_and_profit_taker]
+
+ def orderOperations_cancel(self):
+ if self.simplePlaceOid is not None:
+ # ! [cancelorder]
+ self.cancelOrder(self.simplePlaceOid, OrderSamples.CancelOrderEmpty())
+ # ! [cancelorder]
+
+ # Cancel all orders for all accounts
+ # ! [reqglobalcancel]
+ self.reqGlobalCancel(OrderSamples.CancelOrderEmpty())
+ # ! [reqglobalcancel]
+
+ # Cancel limit order with manual order cancel time
+ if self.simplePlaceOid is not None:
+ # ! [cancel_order_with_manual_order_time]
+ self.cancelOrder(self.simplePlaceOid, OrderSamples.CancelOrderWithManualTime("20240614-00:00:10"))
+ # ! [cancel_order_with_manual_order_time]
+
+ def rerouteCFDOperations(self):
+ # ! [reqmktdatacfd]
+ self.reqMktData(16001, ContractSamples.USStockCFD(), "", False, False, [])
+ self.reqMktData(16002, ContractSamples.EuropeanStockCFD(), "", False, False, [])
+ self.reqMktData(16003, ContractSamples.CashCFD(), "", False, False, [])
+ # ! [reqmktdatacfd]
+
+ # ! [reqmktdepthcfd]
+ self.reqMktDepth(16004, ContractSamples.USStockCFD(), 10, False, [])
+ self.reqMktDepth(16005, ContractSamples.EuropeanStockCFD(), 10, False, [])
+ self.reqMktDepth(16006, ContractSamples.CashCFD(), 10, False, [])
+ # ! [reqmktdepthcfd]
+
+ def marketRuleOperations(self):
+ self.reqContractDetails(17001, ContractSamples.USStock())
+ self.reqContractDetails(17002, ContractSamples.Bond())
+
+ # ! [reqmarketrule]
+ self.reqMarketRule(26)
+ self.reqMarketRule(239)
+ # ! [reqmarketrule]
+
+ def ibkratsSample(self):
+ # ! [ibkratssubmit]
+ ibkratsOrder = OrderSamples.LimitIBKRATS("BUY", 100, 330)
+ self.placeOrder(self.nextOrderId(), ContractSamples.IBKRATSContract(), ibkratsOrder)
+ # ! [ibkratssubmit]
+
+ def configOperations_req(self):
+ # ! [req_config]
+ configRequestProto = ConfigRequestProto()
+ configRequestProto.reqId = 20001
+ self.reqConfigProtoBuf(configRequestProto)
+ # ! [req_config]
+
+ # ! [update_api_settings_config_request]
+ self.updateConfigProtoBuf(ConfigSamples.UpdateConfigApiSettings(20002));
+ # ! [update_api_settings_config_request]
+
+ # ! [update_orders_config_request]
+ self.updateConfigProtoBuf(ConfigSamples.UpdateOrdersConfig(20003));
+ # ! [update_orders_config_request]
+
+ # ! [update_message_config_request]
+ self.updateConfigProtoBuf(ConfigSamples.UpdateMessageConfigConfirmMandatoryCapPriceAccepted(20004));
+ # ! [update_message_config_request]
+
+ # ! [update_config_request_order_id_reset]
+ self.updateConfigProtoBuf(ConfigSamples.UpdateConfigOrderIdReset(20005));
+ # ! [update_config_request_order_id_reset]
+
+ @iswrapper
+ # ! [execdetails]
+ def execDetails(self, reqId: int, contract: Contract, execution: Execution):
+ super().execDetails(reqId, contract, execution)
+ print("ExecDetails. ReqId:", reqId, "Contract - ", contract, "Execution - ", execution)
+ # ! [execdetails]
+
+ @iswrapper
+ # ! [execdetailsend]
+ def execDetailsEnd(self, reqId: int):
+ super().execDetailsEnd(reqId)
+ print("ExecDetailsEnd. ReqId:", reqId)
+ # ! [execdetailsend]
+
+ @iswrapper
+ # ! [commissionandfeesreport]
+ def commissionAndFeesReport(self, commissionAndFeesReport: CommissionAndFeesReport):
+ super().commissionAndFeesReport(commissionAndFeesReport)
+ print("CommissionAndFeesReport.", commissionAndFeesReport)
+ # ! [commissionandfeesreport]
+
+ @iswrapper
+ # ! [currenttime]
+ def currentTime(self, time:int):
+ super().currentTime(time)
+ print("CurrentTime:", time, "-", getTimeStrFromMillis(time * 1000))
+ # ! [currenttime]
+
+ @iswrapper
+ # ! [completedorder]
+ def completedOrder(self, contract: Contract, order: Order,
+ orderState: OrderState):
+ super().completedOrder(contract, order, orderState)
+ print("CompletedOrder. PermId:", longMaxString(order.permId), "ParentPermId:", longMaxString(order.parentPermId), "Account:", order.account,
+ "Symbol:", contract.symbol, "SecType:", contract.secType, "Exchange:", contract.exchange,
+ "Action:", order.action, "OrderType:", order.orderType, "TotalQty:", decimalMaxString(order.totalQuantity),
+ "CashQty:", floatMaxString(order.cashQty), "FilledQty:", decimalMaxString(order.filledQuantity),
+ "LmtPrice:", floatMaxString(order.lmtPrice), "AuxPrice:", floatMaxString(order.auxPrice), "Status:", orderState.status,
+ "Completed time:", orderState.completedTime, "Completed Status:" + orderState.completedStatus,
+ "MinTradeQty:", intMaxString(order.minTradeQty), "MinCompeteSize:", intMaxString(order.minCompeteSize),
+ "competeAgainstBestOffset:", "UpToMid" if order.competeAgainstBestOffset == COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID else floatMaxString(order.competeAgainstBestOffset),
+ "MidOffsetAtWhole:", floatMaxString(order.midOffsetAtWhole),"MidOffsetAtHalf:" ,floatMaxString(order.midOffsetAtHalf), "CustomerAccount:", order.customerAccount,
+ "ProfessionalCustomer:", order.professionalCustomer, "Submitter:", order.submitter, "ImbalanceOnly:", order.imbalanceOnly)
+ # ! [completedorder]
+
+ @iswrapper
+ # ! [completedordersend]
+ def completedOrdersEnd(self):
+ super().completedOrdersEnd()
+ print("CompletedOrdersEnd")
+ # ! [completedordersend]
+
+ @iswrapper
+ # ! [replacefaend]
+ def replaceFAEnd(self, reqId: int, text: str):
+ super().replaceFAEnd(reqId, text)
+ print("ReplaceFAEnd.", "ReqId:", reqId, "Text:", text)
+ # ! [replacefaend]
+
+ @iswrapper
+ # ! [wshmetadata]
+ def wshMetaData(self, reqId: int, dataJson: str):
+ super().wshMetaData(reqId, dataJson)
+ print("WshMetaData.", "ReqId:", reqId, "Data JSON:", dataJson)
+ # ! [wshmetadata]
+
+ @iswrapper
+ # ! [wsheventdata]
+ def wshEventData(self, reqId: int, dataJson: str):
+ super().wshEventData(reqId, dataJson)
+ print("WshEventData.", "ReqId:", reqId, "Data JSON:", dataJson)
+ # ! [wsheventdata]
+
+ @iswrapper
+ # ! [historicalschedule]
+ def historicalSchedule(self, reqId: int, startDateTime: str, endDateTime: str, timeZone: str, sessions: ListOfHistoricalSessions):
+ super().historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions)
+ print("HistoricalSchedule. ReqId:", reqId, "Start:", startDateTime, "End:", endDateTime, "TimeZone:", timeZone)
+
+ for session in sessions:
+ print("\tSession. Start:", session.startDateTime, "End:", session.endDateTime, "Ref Date:", session.refDate)
+ # ! [historicalschedule]
+
+ @iswrapper
+ # ! [userinfo]
+ def userInfo(self, reqId: int, whiteBrandingId: str):
+ super().userInfo(reqId, whiteBrandingId)
+ print("UserInfo.", "ReqId:", reqId, "WhiteBrandingId:", whiteBrandingId)
+ # ! [userinfo]
+
+ @iswrapper
+ # ! [currenttimeinmillis]
+ def currentTimeInMillis(self, timeInMillis: int):
+ super().currentTimeInMillis(timeInMillis)
+ print("CurrentTimeInMillis:", timeInMillis, "-", getTimeStrFromMillis(timeInMillis))
+ # ! [currenttimeinmillis]
+
+ def printTagValueList(self, tagValueList: list[TagValue], listName: str):
+ if tagValueList is not None and tagValueList:
+ print("\t", listName, "{", end=" ")
+ for tagValue in tagValueList:
+ print(tagValue.tag, "=", tagValue.value, end=" ")
+ print("}")
+
+ def printConditions(self, conditions: list[OrderCondition]):
+ if conditions is not None and conditions:
+ print("\tConditions: {", end=" ")
+ for condition in conditions:
+ print(condition, ";", end=" ")
+ print("}")
+
+ def printSoftDollarTier(self, softDollarTier: SoftDollarTier):
+ print("\tSoftDollarTier: {name:", softDollarTier.name, "val:", softDollarTier.val, "displayName:", softDollarTier.displayName, "}");
+
+ def printDeltaNeutralContract(self, deltaNeutralContract: DeltaNeutralContract):
+ if deltaNeutralContract is not None:
+ print("\tDeltaNeutralContract: {conid:", intMaxString(deltaNeutralContract.conId), "delta:", floatMaxString(deltaNeutralContract.delta), "price:" + floatMaxString(deltaNeutralContract.price), "}");
+
+ def printComboLegs(self, comboLegList: list[ComboLeg]):
+ if comboLegList is not None and comboLegList:
+ print("\tComboLegs:{", end=" ");
+ for comboLeg in comboLegList:
+ print("conId: ", intMaxString(comboLeg.conId), "action: ", comboLeg.action, "ratio: ", intMaxString(comboLeg.ratio), "exchange: " + comboLeg.exchange, ";", end=" ");
+ print("}");
+
+ def printOrderComboLegs(self, orderComboLegList: list[OrderComboLeg]):
+ if orderComboLegList is not None and orderComboLegList:
+ print("\tOrderComboLegs:{", end=" ");
+ for orderComboLeg in orderComboLegList:
+ print("price: ", floatMaxString(orderComboLeg.price), ";", end=" ");
+ print("}");
+
+ # Protobuf
+ @iswrapper
+ # ! [orderstatus_protobuf]
+ def orderStatusProtoBuf(self, orderStatusProto: OrderStatusProto):
+ super().orderStatusProtoBuf(orderStatusProto)
+ print("OrderStatusProtoBuf")
+ # ! [orderstatus_protobuf]
+
+ # ! [openorder_protobuf]
+ @iswrapper
+ def openOrderProtoBuf(self, openOrderProto: OpenOrderProto):
+ super().openOrderProtoBuf(openOrderProto)
+ print("OpenOrderProtoBuf")
+ # ! [openorder_protobuf]
+
+ # ! [openordersend_protobuf]
+ @iswrapper
+ def openOrdersEndProtoBuf(self, openOrdersEndProto: OpenOrdersEndProto):
+ super().openOrdersEndProtoBuf(openOrdersEndProto)
+ print("OpenOrdersEndProtoBuf")
+ # ! [openordersend_protobuf]
+
+ # ! [errormessage_protobuf]
+ @iswrapper
+ def errorProtoBuf(self, errorMessageProto: ErrorMessageProto):
+ super().errorProtoBuf(errorMessageProto)
+ print("ErrorProtoBuf")
+ # ! [errormessage_protobuf]
+
+ # ! [executiondetails_protobuf]
+ @iswrapper
+ def executionDetailsProtoBuf(self, executionDetailsProto: ExecutionDetailsProto):
+ super().executionDetailsProtoBuf(executionDetailsProto)
+ print("ExecutionDetailsProtoBuf")
+ # ! [executiondetails_protobuf]
+
+ # ! [executiondetailsend_protobuf]
+ @iswrapper
+ def executionDetailsEndProtoBuf(self, executionDetailsEndProto: ExecutionDetailsProto):
+ super().executionDetailsEndProtoBuf(executionDetailsEndProto)
+ print("ExecutionDetailsEndProtoBuf")
+ # ! [executiondetailsend_protobuf]
+
+ # ! [completedorder_protobuf]
+ @iswrapper
+ def completedOrderProtoBuf(self, completedOrderProto: CompletedOrderProto):
+ super().completedOrderProtoBuf(completedOrderProto)
+ print("CompletedOrderProtoBuf")
+ # ! [completedorder_protobuf]
+
+ # ! [completedordersend_protobuf]
+ @iswrapper
+ def completedOrdersEndProtoBuf(self, completedOrdersEndProto: CompletedOrdersEndProto):
+ super().completedOrdersEndProtoBuf(completedOrdersEndProto)
+ print("CompletedOrdersEndProtoBuf")
+ # ! [completedordersend_protobuf]
+
+ # ! [orderbound_protobuf]
+ @iswrapper
+ def orderBoundProtoBuf(self, orderBoundProto: OrderBoundProto):
+ super().orderBoundProtoBuf(orderBoundProto)
+ print("OrderBoundProtoBuf")
+ # ! [orderbound_protobuf]
+
+ # ! [contractdata_protobuf]
+ @iswrapper
+ def contractDataProtoBuf(self, contractDataProto: ContractDataProto):
+ super().contractDataProtoBuf(contractDataProto)
+ print("ContractDataProtoBuf")
+ # ! [contractdata_protobuf]
+
+ # ! [bondcontractdata_protobuf]
+ @iswrapper
+ def bondContractDataProtoBuf(self, contractDataProto: ContractDataProto):
+ super().bondContractDataProtoBuf(contractDataProto)
+ print("BondContractDataProtoBuf")
+ # ! [bondcontractdata_protobuf]
+
+ # ! [contractdataend_protobuf]
+ @iswrapper
+ def contractDataEndProtoBuf(self, contractDataEndProto: ContractDataEndProto):
+ super().contractDataEndProtoBuf(contractDataEndProto)
+ print("ContractDataEndProtoBuf")
+ # ! [contractdataend_protobuf]
+
+ # ! [tickprice_protobuf]
+ @iswrapper
+ def tickPriceProtoBuf(self, tickPriceProto: TickPriceProto):
+ super().tickPriceProtoBuf(tickPriceProto)
+ print("TickPriceProtoBuf")
+ # ! [tickprice_protobuf]
+
+ # ! [ticksize_protobuf]
+ @iswrapper
+ def tickSizeProtoBuf(self, tickSizeProto: TickSizeProto):
+ super().tickSizeProtoBuf(tickSizeProto)
+ print("TickSizeProtoBuf")
+ # ! [ticksize_protobuf]
+
+ # ! [tickoptioncomputation_protobuf]
+ @iswrapper
+ def tickOptionComputationProtoBuf(self, tickOptionComputationProto: TickOptionComputationProto):
+ super().tickOptionComputationProtoBuf(tickOptionComputationProto)
+ print("TickOptionComputationProtoBuf")
+ # ! [tickoptioncomputation_protobuf]
+
+ # ! [tickgeneric_protobuf]
+ @iswrapper
+ def tickGenericProtoBuf(self, tickGenericProto: TickGenericProto):
+ super().tickGenericProtoBuf(tickGenericProto)
+ print("TickGenericProtoBuf")
+ # ! [tickgeneric_protobuf]
+
+ # ! [tickstring_protobuf]
+ @iswrapper
+ def tickStringProtoBuf(self, tickStringProto: TickStringProto):
+ super().tickStringProtoBuf(tickStringProto)
+ print("TickStringProtoBuf")
+ # ! [tickstring_protobuf]
+
+ # ! [ticksnapshotend_protobuf]
+ @iswrapper
+ def tickSnapshotEndProtoBuf(self, tickSnapshotEndProto: TickSnapshotEndProto):
+ super().tickSnapshotEndProtoBuf(tickSnapshotEndProto)
+ print("TickSnapshotEndProtoBuf")
+ # ! [ticksnapshotend_protobuf]
+
+ # ! [updatemarketdepth_protobuf]
+ @iswrapper
+ def updateMarketDepthProtoBuf(self, marketDepthProto: MarketDepthProto):
+ super().updateMarketDepthProtoBuf(marketDepthProto)
+ print("UpdateMarketDepthProtoBuf")
+ # ! [updatemarketdepth_protobuf]
+
+ # ! [updatemarketdepthl2_protobuf]
+ @iswrapper
+ def updateMarketDepthL2ProtoBuf(self, marketDepthL2Proto: MarketDepthL2Proto):
+ super().updateMarketDepthL2ProtoBuf(marketDepthL2Proto)
+ print("UpdateMarketDepthL2ProtoBuf")
+ # ! [updatemarketdepthl2_protobuf]
+
+ # ! [updatemarketdatatype_protobuf]
+ @iswrapper
+ def updateMarketDataTypeProtoBuf(self, marketDataTypeProto: MarketDataTypeProto):
+ super().updateMarketDataTypeProtoBuf(marketDataTypeProto)
+ print("UpdateMarketDataTypeProtoBuf")
+ # ! [updatemarketdatatype_protobuf]
+
+ # ! [tickreqparams_protobuf]
+ @iswrapper
+ def tickReqParamsProtoBuf(self, tickReqParamsProto: TickReqParamsProto):
+ super().tickReqParamsProtoBuf(tickReqParamsProto)
+ parts = [
+ f"TickerId: {tickReqParamsProto.reqId}" if tickReqParamsProto.HasField('reqId') else None,
+ f"MinTick: {tickReqParamsProto.minTick}" if tickReqParamsProto.HasField('minTick') else None,
+ f"BboExchange: {tickReqParamsProto.bboExchange}" if tickReqParamsProto.HasField('bboExchange') else None,
+ f"SnapshotPermissions: {tickReqParamsProto.snapshotPermissions}" if tickReqParamsProto.HasField('snapshotPermissions') else None,
+ f"LastPricePrecision: {tickReqParamsProto.lastPricePrecision}" if tickReqParamsProto.HasField('lastPricePrecision') else None,
+ f"LastSizePrecision: {tickReqParamsProto.lastSizePrecision}" if tickReqParamsProto.HasField('lastSizePrecision') else None,
+ ]
+ tickReqParamsStr = " ".join(filter(None, parts))
+ print("TickReqParams.", tickReqParamsStr)
+ # ! [tickreqparams_protobuf]
+
+ # ! [updateaccountvalue_protobuf]
+ @iswrapper
+ def updateAccountValueProtoBuf(self, accountValueProto: AccountValueProto):
+ super().updateAccountValueProtoBuf(accountValueProto)
+ print("UpdateAccountValueProtoBuf")
+ # ! [updateaccountvalue_protobuf]
+
+ # ! [updateportfolio_protobuf]
+ @iswrapper
+ def updatePortfolioProtoBuf(self, portfolioValueProto: PortfolioValueProto):
+ super().updatePortfolioProtoBuf(portfolioValueProto)
+ print("UpdatePortfolioProtoBuf")
+ # ! [updateportfolio_protobuf]
+
+ # ! [updateaccounttime_protobuf]
+ @iswrapper
+ def updateAccountTimeProtoBuf(self, accountUpdateTimeProto: AccountUpdateTimeProto):
+ super().updateAccountTimeProtoBuf(accountUpdateTimeProto)
+ print("UpdateAccountTimeProtoBuf")
+ # ! [updateaccounttime_protobuf]
+
+ # ! [accountdataend_protobuf]
+ @iswrapper
+ def accountDataEndProtoBuf(self, accountDataEndProto: AccountDataEndProto):
+ super().accountDataEndProtoBuf(accountDataEndProto)
+ print("AccountDataEndProtoBuf")
+ # ! [accountdataend_protobuf]
+
+ # ! [managedaccounts_protobuf]
+ @iswrapper
+ def managedAccountsProtoBuf(self, managedAccountsProto: ManagedAccountsProto):
+ super().managedAccountsProtoBuf(managedAccountsProto)
+ print("ManagedAccountsProtoBuf")
+ # ! [managedaccounts_protobuf]
+
+ # ! [position_protobuf]
+ @iswrapper
+ def positionProtoBuf(self, positionProto: PositionProto):
+ super().positionProtoBuf(positionProto)
+ print("PositionProtoBuf")
+ # ! [position_protobuf]
+
+ # ! [positionend_protobuf]
+ @iswrapper
+ def positionEndProtoBuf(self, positionEndProto: PositionEndProto):
+ super().positionEndProtoBuf(positionEndProto)
+ print("PositionEndProtoBuf")
+ # ! [positionend_protobuf]
+
+ # ! [accountsummary_protobuf]
+ @iswrapper
+ def accountSummaryProtoBuf(self, accountSummaryProto: AccountSummaryProto):
+ super().accountSummaryProtoBuf(accountSummaryProto)
+ print("AccountSummaryProtoBuf")
+ # ! [accountsummary_protobuf]
+
+ # ! [accountsummaryend_protobuf]
+ @iswrapper
+ def accountSummaryEndProtoBuf(self, accountSummaryEndProto: AccountSummaryEndProto):
+ super().accountSummaryEndProtoBuf(accountSummaryEndProto)
+ print("AccountSummaryEndProtoBuf")
+ # ! [accountsummaryend_protobuf]
+
+ # ! [positionmulti_protobuf]
+ @iswrapper
+ def positionMultiProtoBuf(self, positionMultiProto: PositionMultiProto):
+ super().positionMultiProtoBuf(positionMultiProto)
+ print("PositionMultiProtoBuf")
+ # ! [positionmulti_protobuf]
+
+ # ! [positionmultiend_protobuf]
+ @iswrapper
+ def positionMultiEndProtoBuf(self, positionMultiEndProto: PositionMultiEndProto):
+ super().positionMultiEndProtoBuf(positionMultiEndProto)
+ print("PositionMultiEndProtoBuf")
+ # ! [positionmultiend_protobuf]
+
+ # ! [accountupdatemulti_protobuf]
+ @iswrapper
+ def accountUpdateMultiProtoBuf(self, accountUpdateMultiProto: AccountUpdateMultiProto):
+ super().accountUpdateMultiProtoBuf(accountUpdateMultiProto)
+ print("AccountUpdateMultiProtoBuf")
+ # ! [accountupdatemulti_protobuf]
+
+ # ! [accountupdatemultiend_protobuf]
+ @iswrapper
+ def accountUpdateMultiEndProtoBuf(self, accountUpdateMultiEndProto: AccountUpdateMultiEndProto):
+ super().accountUpdateMultiEndProtoBuf(accountUpdateMultiEndProto)
+ print("AccountUpdateMultiEndProtoBuf")
+ # ! [accountupdatemultiend_protobuf]
+
+ # ! [historicaldata_protobuf]
+ @iswrapper
+ def historicalDataProtoBuf(self, historicalDataProto: HistoricalDataProto):
+ super().historicalDataProtoBuf(historicalDataProto)
+ print("HistoricalDataProtoBuf")
+ # ! [historicaldata_protobuf]
+
+ # ! [historicaldataupdate_protobuf]
+ @iswrapper
+ def historicalDataUpdateProtoBuf(self, historicalDataUpdateProto: HistoricalDataUpdateProto):
+ super().historicalDataUpdateProtoBuf(historicalDataUpdateProto)
+ print("HistoricalDataUpdateProtoBuf")
+ # ! [historicaldataupdate_protobuf]
+
+ # ! [historicaldataend_protobuf]
+ @iswrapper
+ def historicalDataEndProtoBuf(self, historicalDataEndProto: HistoricalDataEndProto):
+ super().historicalDataEndProtoBuf(historicalDataEndProto)
+ print("HistoricalDataEndProtoBuf")
+ # ! [historicaldataend_protobuf]
+
+ # ! [realtimebartick_protobuf]
+ @iswrapper
+ def realTimeBarTickProtoBuf(self, realTimeBarTickProto: RealTimeBarTickProto):
+ super().realTimeBarTickProtoBuf(realTimeBarTickProto)
+ print("RealTimeBarTickProtoBuf")
+ # ! [realtimebartick_protobuf]
+
+ # ! [headtimestamp_protobuf]
+ @iswrapper
+ def headTimestampProtoBuf(self, headTimestampProto: HeadTimestampProto):
+ super().headTimestampProtoBuf(headTimestampProto)
+ print("HeadTimestampProtoBuf")
+ # ! [headtimestamp_protobuf]
+
+ # ! [histogramdata_protobuf]
+ @iswrapper
+ def histogramDataProtoBuf(self, histogramDataProto: HistogramDataProto):
+ super().histogramDataProtoBuf(histogramDataProto)
+ print("HistogramDataProtoBuf")
+ # ! [histogramdata_protobuf]
+
+ # ! [historicalticks_protobuf]
+ @iswrapper
+ def historicalTicksProtoBuf(self, historicalTicksProto: HistoricalTicksProto):
+ super().historicalTicksProtoBuf(historicalTicksProto)
+ print("HistoricalTicksProtoBuf")
+ # ! [historicalticks_protobuf]
+
+ # ! [historicalticksbidask_protobuf]
+ @iswrapper
+ def historicalTicksBidAskProtoBuf(self, historicalTicksBidAskProto: HistoricalTicksBidAskProto):
+ super().historicalTicksBidAskProtoBuf(historicalTicksBidAskProto)
+ print("HistoricalTicksBidAskProtoBuf")
+ # ! [historicalticksbidask_protobuf]
+
+ # ! [historicaltickslast_protobuf]
+ @iswrapper
+ def historicalTicksLastProtoBuf(self, historicalTicksLastProto: HistoricalTicksLastProto):
+ super().historicalTicksLastProtoBuf(historicalTicksLastProto)
+ print("HistoricalTicksLastProtoBuf")
+ # ! [historicaltickslast_protobuf]
+
+ # ! [tickbytickdata_protobuf]
+ @iswrapper
+ def tickByTickDataProtoBuf(self, tickByTickDataProto: TickByTickDataProto):
+ super().tickByTickDataProtoBuf(tickByTickDataProto)
+ print("TickByTickDatatProtoBuf")
+ # ! [tickbytickdata_protobuf]
+
+ # ! [updatenewsbulletin_protobuf]
+ @iswrapper
+ def updateNewsBulletinProtoBuf(self, newsBulletinProto: NewsBulletinProto):
+ super().updateNewsBulletinProtoBuf(newsBulletinProto)
+ print("UpdateNewsBulletinProtoBuf")
+ # ! [updatenewsbulletin_protobuf]
+
+ # ! [newsarticle_protobuf]
+ @iswrapper
+ def newsArticleProtoBuf(self, newsArticleProto: NewsArticleProto):
+ super().newsArticleProtoBuf(newsArticleProto)
+ print("NewsArticleProtoBuf")
+ # ! [newsarticle_protobuf]
+
+ # ! [newsproviders_protobuf]
+ @iswrapper
+ def newsProvidersProtoBuf(self, newsProvidersProto: NewsProvidersProto):
+ super().newsProvidersProtoBuf(newsProvidersProto)
+ print("NewsProvidersProtoBuf")
+ # ! [newsproviders_protobuf]
+
+ # ! [historicalnews_protobuf]
+ @iswrapper
+ def historicalNewsProtoBuf(self, historicalNewsProto: HistoricalNewsProto):
+ super().historicalNewsProtoBuf(historicalNewsProto)
+ print("HistoricalNewsProtoBuf")
+ # ! [historicalnews_protobuf]
+
+ # ! [historicalnewsend_protobuf]
+ @iswrapper
+ def historicalNewsEndProtoBuf(self, historicalNewsEndProto: HistoricalNewsEndProto):
+ super().historicalNewsEndProtoBuf(historicalNewsEndProto)
+ print("HistoricalNewsEndProtoBuf")
+ # ! [historicalnewsend_protobuf]
+
+ # ! [wshmetadata_protobuf]
+ @iswrapper
+ def wshMetaDataProtoBuf(self, wshMetaDataProto: WshMetaDataProto):
+ super().wshMetaDataProtoBuf(wshMetaDataProto)
+ print("WshMetaDataProtoBuf")
+ # ! [wshmetadata_protobuf]
+
+ # ! [wsheventdata_protobuf]
+ @iswrapper
+ def wshEventDataProtoBuf(self, wshEventDataProto: WshEventDataProto):
+ super().wshEventDataProtoBuf(wshEventDataProto)
+ print("WshEventDataProtoBuf")
+ # ! [wsheventdata_protobuf]
+
+ # ! [ticknews_protobuf]
+ @iswrapper
+ def tickNewsProtoBuf(self, tickNewsProto: TickNewsProto):
+ super().tickNewsProtoBuf(tickNewsProto)
+ print("TickNewsProtoBuf")
+ # ! [ticknews_protobuf]
+
+ # ! [scannerparameters_protobuf]
+ @iswrapper
+ def scannerParametersProtoBuf(self, scannerParametersProto: ScannerParametersProto):
+ super().scannerParametersProtoBuf(scannerParametersProto)
+ print("ScannerParametersProtoBuf")
+ # ! [scannerparameters_protobuf]
+
+ # ! [scannerdata_protobuf]
+ @iswrapper
+ def scannerDataProtoBuf(self, scannerDataProto: ScannerDataProto):
+ super().scannerDataProtoBuf(scannerDataProto)
+ print("ScannerDataProtoBuf")
+ # ! [scannerdata_protobuf]
+
+ # ! [fundamentalsdata_protobuf]
+ @iswrapper
+ def fundamentalsDataProtoBuf(self, fundamentalsDataProto: FundamentalsDataProto):
+ super().fundamentalsDataProtoBuf(fundamentalsDataProto)
+ print("FundamentalsDataProtoBuf")
+ # ! [fundamentalsdata_protobuf]
+
+ # ! [pnl_protobuf]
+ @iswrapper
+ def pnlProtoBuf(self, pnlProto: PnLProto):
+ super().pnlProtoBuf(pnlProto)
+ print("PnLProtoBuf")
+ # ! [pnl_protobuf]
+
+ # ! [pnlsingle_protobuf]
+ @iswrapper
+ def pnlSingleProtoBuf(self, pnlSingleProto: PnLSingleProto):
+ super().pnlSingleProtoBuf(pnlSingleProto)
+ print("PnLSingleProtoBuf")
+ # ! [pnlsingle_protobuf]
+
+ # ! [receivefa_protobuf]
+ @iswrapper
+ def receiveFAProtoBuf(self, receiveFAProto: ReceiveFAProto):
+ super().receiveFAProtoBuf(receiveFAProto)
+ print("ReceiveFAProtoBuf")
+ # ! [receivefa_protobuf]
+
+ # ! [replacefaend_protobuf]
+ @iswrapper
+ def replaceFAEndProtoBuf(self, replaceFAEndProto: ReplaceFAEndProto):
+ super().replaceFAEndProtoBuf(replaceFAEndProto)
+ print("ReplaceFAEndProtoBuf")
+ # ! [replacefaend_protobuf]
+
+ # ! [commissionandfeesreport_protobuf]
+ @iswrapper
+ def commissionAndFeesReportProtoBuf(self, commissionAndFeesReportProto: CommissionAndFeesReportProto):
+ super().commissionAndFeesReportProtoBuf(commissionAndFeesReportProto)
+ print("CommissionAndFeesReportProtoBuf")
+ # ! [commissionandfeesreport_protobuf]
+
+ # ! [historicalschedule_protobuf]
+ @iswrapper
+ def historicalScheduleProtoBuf(self, historicalScheduleProto: HistoricalScheduleProto):
+ super().historicalScheduleProtoBuf(historicalScheduleProto)
+ print("HistoricalScheduleProtoBuf")
+ # ! [historicalschedule_protobuf]
+
+ # ! [reroutemarketdatarequest_protobuf]
+ @iswrapper
+ def rerouteMarketDataRequestProtoBuf(self, rerouteMarketDataRequestProto: RerouteMarketDataRequestProto):
+ super().rerouteMarketDataRequestProtoBuf(rerouteMarketDataRequestProto)
+ print("RerouteMarketDataRequestProtoBuf")
+ # ! [reroutemarketdatarequest_protobuf]
+
+ # ! [reroutemarketdepthrequest_protobuf]
+ @iswrapper
+ def rerouteMarketDepthRequestProtoBuf(self, rerouteMarketDepthRequestProto: RerouteMarketDepthRequestProto):
+ super().rerouteMarketDepthRequestProtoBuf(rerouteMarketDepthRequestProto)
+ print("RerouteMarketDepthRequestProtoBuf")
+ # ! [reroutemarketdepthrequest_protobuf]
+
+ # ! [secdefoptparameter_protobuf]
+ @iswrapper
+ def secDefOptParameterProtoBuf(self, secDefOptParameterProto: SecDefOptParameterProto):
+ super().secDefOptParameterProtoBuf(secDefOptParameterProto)
+ print("SecDefOptParameterProtoBuf")
+ # ! [secdefoptparameter_protobuf]
+
+ # ! [secdefoptparameterend_protobuf]
+ @iswrapper
+ def secDefOptParameterEndProtoBuf(self, secDefOptParameterEndProto: SecDefOptParameterEndProto):
+ super().secDefOptParameterEndProtoBuf(secDefOptParameterEndProto)
+ print("SecDefOptParameterEndProtoBuf")
+ # ! [secdefoptparameterend_protobuf]
+
+ # ! [softdollartiers_protobuf]
+ @iswrapper
+ def softDollarTiersProtoBuf(self, softDollarTiersProto: SoftDollarTiersProto):
+ super().softDollarTiersProtoBuf(softDollarTiersProto)
+ print("SoftDollarTiersProtoBuf")
+ # ! [softdollartiers_protobuf]
+
+ # ! [familycodes_protobuf]
+ @iswrapper
+ def familyCodesProtoBuf(self, familyCodesProto: FamilyCodesProto):
+ super().familyCodesProtoBuf(familyCodesProto)
+ print("FamilyCodesProtoBuf")
+ # ! [familycodes_protobuf]
+
+ # ! [symbolsamples_protobuf]
+ @iswrapper
+ def symbolSamplesProtoBuf(self, symbolSamplesProto: SymbolSamplesProto):
+ super().symbolSamplesProtoBuf(symbolSamplesProto)
+ print("SymbolSamplesProtoBuf")
+ # ! [symbolsamples_protobuf]
+
+ # ! [smartcomponents_protobuf]
+ @iswrapper
+ def smartComponentsProtoBuf(self, smartComponentsProto: SmartComponentsProto):
+ super().smartComponentsProtoBuf(smartComponentsProto)
+ print("SmartComponentsProtoBuf")
+ # ! [smartcomponents_protobuf]
+
+ # ! [marketrule_protobuf]
+ @iswrapper
+ def marketRuleProtoBuf(self, marketRuleProto: MarketRuleProto):
+ super().marketRuleProtoBuf(marketRuleProto)
+ print("MarketRuleProtoBuf")
+ # ! [marketrule_protobuf]
+
+ # ! [userinfo_protobuf]
+ @iswrapper
+ def userInfoProtoBuf(self, userInfoProto: UserInfoProto):
+ super().userInfoProtoBuf(userInfoProto)
+ print("UserInfoProtoBuf")
+ # ! [userinfo_protobuf]
+
+ # ! [nextvalidid_protobuf]
+ @iswrapper
+ def nextValidIdProtoBuf(self, nextValidIdProto: NextValidIdProto):
+ super().nextValidIdProtoBuf(nextValidIdProto)
+ print("NextValidIdProtoBuf")
+ # ! [nextvalidid_protobuf]
+
+ # ! [currenttime_protobuf]
+ @iswrapper
+ def currentTimeProtoBuf(self, currentTimeProto: CurrentTimeProto):
+ super().currentTimeProtoBuf(currentTimeProto)
+ print("CurrentTimeProtoBuf")
+ # ! [currenttime_protobuf]
+
+ # ! [currenttimeinmillis_protobuf]
+ @iswrapper
+ def currentTimeInMillisProtoBuf(self, currentTimeInMillisProto: CurrentTimeInMillisProto):
+ super().currentTimeInMillisProtoBuf(currentTimeInMillisProto)
+ print("CurrentTimeInMillisProtoBuf")
+ # ! [currenttimeinmillis_protobuf]
+
+ # ! [verifymessageapi_protobuf]
+ @iswrapper
+ def verifyMessageApiProtoBuf(self, verifyMessageApiProto: VerifyMessageApiProto):
+ super().verifyMessageApiProtoBuf(verifyMessageApiProto)
+ print("VerifyMessageApiProtoBuf")
+ # ! [verifymessageapi_protobuf]
+
+ # ! [verifycompleted_protobuf]
+ @iswrapper
+ def verifyCompletedProtoBuf(self, verifyCompletedProto: VerifyCompletedProto):
+ super().verifyCompletedProtoBuf(verifyCompletedProto)
+ print("VerifyCompletedProtoBuf")
+ # ! [verifycompleted_protobuf]
+
+ # ! [displaygrouplist_protobuf]
+ @iswrapper
+ def displayGroupListProtoBuf(self, displayGroupListProto: DisplayGroupListProto):
+ super().displayGroupListProtoBuf(displayGroupListProto)
+ print("DisplayGroupListProtoBuf")
+ # ! [displaygrouplist_protobuf]
+
+ # ! [displaygroupupdated_protobuf]
+ @iswrapper
+ def displayGroupUpdatedProtoBuf(self, displayGroupUpdatedProto: DisplayGroupUpdatedProto):
+ super().displayGroupUpdatedProtoBuf(displayGroupUpdatedProto)
+ print("DisplayGroupUpdatedProtoBuf")
+ # ! [displaygroupupdated_protobuf]
+
+ # ! [marketdepthexchanges_protobuf]
+ @iswrapper
+ def marketDepthExchangesProtoBuf(self, marketDepthExchangesProto: MarketDepthExchangesProto):
+ super().marketDepthExchangesProtoBuf(marketDepthExchangesProto)
+ print("MarketDepthExchangesProtoBuf")
+ # ! [marketdepthexchanges_protobuf]
+
+ # ! [config_response_protobuf]
+ @iswrapper
+ def configResponseProtoBuf(self, configResponseProto: ConfigResponseProto):
+ super().configResponseProtoBuf(configResponseProto)
+ print("==== Config Response Begin ====")
+ print(configResponseProto)
+ print("==== Config Response End ====")
+ # ! [config_response_protobuf]
+
+ # ! [update_config_response_protobuf]
+ @iswrapper
+ def updateConfigResponseProtoBuf(self, updateConfigResponseProto: UpdateConfigResponseProto):
+ super().updateConfigResponseProtoBuf(updateConfigResponseProto)
+ print("==== Update Config Response Begin ====")
+ print(updateConfigResponseProto)
+ print("==== Update Config Response End ====")
+ # ! [update_config_response_protobuf]
+
+def main():
+ SetupLogger()
+ logging.debug("now is %s", datetime.datetime.now())
+ logging.getLogger().setLevel(logging.ERROR)
+
+ cmdLineParser = argparse.ArgumentParser("api tests")
+ # cmdLineParser.add_option("-c", action="store_True", dest="use_cache", default = False, help = "use the cache")
+ # cmdLineParser.add_option("-f", action="store", type="string", dest="file", default="", help="the input file")
+ cmdLineParser.add_argument("-p", "--port", action="store", type=int,
+ dest="port", default=7496, help="The TCP port to use")
+ cmdLineParser.add_argument("-C", "--global-cancel", action="store_true",
+ dest="global_cancel", default=False,
+ help="whether to trigger a globalCancel req")
+ args = cmdLineParser.parse_args()
+ print("Using args", args)
+ logging.debug("Using args %s", args)
+ # print(args)
+
+
+ # enable logging when member vars are assigned
+ from ibapi import utils
+ Order.__setattr__ = utils.setattr_log
+ Contract.__setattr__ = utils.setattr_log
+ DeltaNeutralContract.__setattr__ = utils.setattr_log
+ TagValue.__setattr__ = utils.setattr_log
+ TimeCondition.__setattr__ = utils.setattr_log
+ ExecutionCondition.__setattr__ = utils.setattr_log
+ MarginCondition.__setattr__ = utils.setattr_log
+ PriceCondition.__setattr__ = utils.setattr_log
+ PercentChangeCondition.__setattr__ = utils.setattr_log
+ VolumeCondition.__setattr__ = utils.setattr_log
+
+ # from inspect import signature as sig
+ # import code code.interact(local=dict(globals(), **locals()))
+ # sys.exit(1)
+
+ # tc = TestClient(None)
+ # tc.reqMktData(1101, ContractSamples.USStockAtSmart(), "", False, None)
+ # print(tc.reqId2nReq)
+ # sys.exit(1)
+
+ try:
+ app = TestApp()
+ if args.global_cancel:
+ app.globalCancelOnly = True
+ # ! [connect]
+ app.setConnectOptions("+PACEAPI")
+ app.connect("127.0.0.1", args.port, clientId=0)
+ # ! [connect]
+ print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),
+ app.twsConnectionTime()))
+
+ # ! [clientrun]
+ app.run()
+ # ! [clientrun]
+ except:
+ raise
+ finally:
+ app.dumpTestCoverageSituation()
+ app.dumpReqAnsErrSituation()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/packages/ibkr/ref/samples/Python/Testbed/ScannerSubscriptionSamples.py b/packages/ibkr/ref/samples/Python/Testbed/ScannerSubscriptionSamples.py
new file mode 100644
index 00000000..2fa6ec60
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/ScannerSubscriptionSamples.py
@@ -0,0 +1,77 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+from ibapi.object_implem import Object
+from ibapi.scanner import ScannerSubscription
+
+
+class ScannerSubscriptionSamples(Object):
+
+ @staticmethod
+ def HotUSStkByVolume():
+ #! [hotusvolume]
+ #Hot US stocks by volume
+ scanSub = ScannerSubscription()
+ scanSub.instrument = "STK"
+ scanSub.locationCode = "STK.US.MAJOR"
+ scanSub.scanCode = "HOT_BY_VOLUME"
+ #! [hotusvolume]
+ return scanSub
+
+ @staticmethod
+ def TopPercentGainersIbis():
+ #! [toppercentgaineribis]
+ # Top % gainers at IBIS
+ scanSub = ScannerSubscription()
+ scanSub.instrument = "STOCK.EU"
+ scanSub.locationCode = "STK.EU.IBIS"
+ scanSub.scanCode = "TOP_PERC_GAIN"
+ #! [toppercentgaineribis]
+ return scanSub
+
+ @staticmethod
+ def MostActiveFutEurex():
+ #! [mostactivefuteurex]
+ # Most active futures at EUREX
+ scanSub = ScannerSubscription()
+ scanSub.instrument = "FUT.EU"
+ scanSub.locationCode = "FUT.EU.EUREX"
+ scanSub.scanCode = "MOST_ACTIVE"
+ #! [mostactivefuteurex]
+ return scanSub
+
+ @staticmethod
+ def HighOptVolumePCRatioUSIndexes():
+ #! [highoptvolume]
+ # High option volume P/C ratio US indexes
+ scanSub = ScannerSubscription()
+ scanSub.instrument = "IND.US"
+ scanSub.locationCode = "IND.US"
+ scanSub.scanCode = "HIGH_OPT_VOLUME_PUT_CALL_RATIO"
+ #! [highoptvolume]
+ return scanSub
+
+ @staticmethod
+ def ComplexOrdersAndTrades():
+ #! [combolatesttrade]
+ # High option volume P/C ratio US indexes
+ scanSub = ScannerSubscription()
+ scanSub.instrument = "NATCOMB"
+ scanSub.locationCode = "NATCOMB.OPT.US"
+ scanSub.scanCode = "COMBO_LATEST_TRADE"
+ #! [combolatesttrade]
+ return scanSub
+
+def Test():
+ print(ScannerSubscriptionSamples.HotUSStkByVolume())
+ print(ScannerSubscriptionSamples.TopPercentGainersIbis())
+ print(ScannerSubscriptionSamples.MostActiveFutEurex())
+ print(ScannerSubscriptionSamples.HighOptVolumePCRatioUSIndexes())
+
+
+if "__main__" == __name__:
+ Test()
+
diff --git a/packages/ibkr/ref/samples/Python/Testbed/Testbed.pyproj b/packages/ibkr/ref/samples/Python/Testbed/Testbed.pyproj
new file mode 100644
index 00000000..b045c996
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/Testbed.pyproj
@@ -0,0 +1,39 @@
+
+
+
+ Debug
+ 2.0
+ {cde8f229-c826-4fb6-ac32-ecf05a7fc489}
+
+ Program.py
+ ..\..\..\source\pythonclient
+ .
+ .
+ {888888a0-9f3d-457c-b088-3a5042f75d52}
+ Standard Python launcher
+
+
+
+
+
+ 10.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ibapi
+ {aa7df1c2-6d30-4556-b6d5-a188f972bbdd}
+ True
+
+
+
+
\ No newline at end of file
diff --git a/packages/ibkr/ref/samples/Python/Testbed/Testbed.sln b/packages/ibkr/ref/samples/Python/Testbed/Testbed.sln
new file mode 100644
index 00000000..5526164f
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/Testbed.sln
@@ -0,0 +1,24 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26430.16
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "Testbed", "Testbed.pyproj", "{CDE8F229-C826-4FB6-AC32-ECF05A7FC489}"
+EndProject
+Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "ibapi", "..\..\..\source\pythonclient\ibapi\ibapi.pyproj", "{AA7DF1C2-6D30-4556-B6D5-A188F972BBDD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CDE8F229-C826-4FB6-AC32-ECF05A7FC489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CDE8F229-C826-4FB6-AC32-ECF05A7FC489}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AA7DF1C2-6D30-4556-B6D5-A188F972BBDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AA7DF1C2-6D30-4556-B6D5-A188F972BBDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/packages/ibkr/ref/samples/Python/Testbed/sync_tester.py b/packages/ibkr/ref/samples/Python/Testbed/sync_tester.py
new file mode 100644
index 00000000..72b8634b
--- /dev/null
+++ b/packages/ibkr/ref/samples/Python/Testbed/sync_tester.py
@@ -0,0 +1,105 @@
+'''
+2002-2025: Use is subject to Interactive Brokers TWS API Non-Commercial License ("License") terms.
+This License is NOT for anybody who is developing software applications that they wish to: (a) sell to third
+party users for a fee, or (b) give to third party users to generate an indirect financial benefit (e.g.,
+commissions). If You wish to make a software application for the purposes described in the preceding
+sentence then please contact Interactive Brokers
+'''
+
+from ibapi.sync_wrapper import TWSSyncWrapper
+from ibapi.contract import Contract
+from ibapi.order import Order
+from time import sleep
+
+# Create the wrapper
+tws = TWSSyncWrapper(timeout=10) # 10 seconds timeout
+'''
+This file is constructed to provide a sample of our new (10.40) TWS API
+Sync Wrapper implementation. This sync wrapper allows users to utilize
+the Trader Workstation API in a synchronized structure rather than our
+standard asynchronous implementation.
+
+Please see ibapi/sync_wrapper for more information.
+'''
+try:
+ # Connect to TWS
+ if not tws.connect_and_start("127.0.0.1", 7496, 0):
+ print("Failed to connect to TWS")
+ exit(1)
+
+ print("Connected to TWS")
+
+ # Get server time
+ try:
+ time_value = tws.get_current_time()
+ print(f"Server time: {time_value}")
+ except Exception as e:
+ print(f"Error getting server time: {e}")
+
+ # Define a contract (e.g., AAPL stock)
+ contract = Contract()
+ contract.symbol = "AAPL"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+
+ # Get contract details
+ try:
+ details = tws.get_contract_details(contract)
+ print(f"Contract details: {details[0].longName if details else 'No details'}")
+ except Exception as e:
+ print(f"Error getting contract details: {e}")
+
+ # Get market data snapshot
+ try:
+ market_data = tws.get_market_data_snapshot(contract)
+ print(f"Market data: {market_data}")
+ except Exception as e:
+ print(f"Error getting market data: {e}")
+
+ # Get historical data
+ try:
+ bars = tws.get_historical_data(
+ contract=contract,
+ end_date_time="", # Empty for current time
+ duration_str="1 D",
+ bar_size_setting="1 hour",
+ what_to_show="TRADES",
+ use_rth=True
+ )
+ print(f"Historical data: {len(bars)} bars")
+ for bar in bars[:3]: # Print first 3 bars
+ print(f" {bar.date}: O={bar.open}, H={bar.high}, L={bar.low}, C={bar.close}, V={bar.volume}")
+ except Exception as e:
+ print(f"Error getting historical data: {e}")
+
+ # Place a limit order (example only - won't execute)
+ try:
+ order = Order()
+ order.action = "BUY"
+ order.orderType = "LMT"
+ order.totalQuantity = 1
+ order.lmtPrice = 100 # Set a low price so it won't execute
+ order.whatIf = True
+
+ order_status = tws.place_order_sync(contract, order)
+ print(f"Order placed: {order_status}")
+
+ # Cancel the order
+ cancel_status = tws.cancel_order_sync(order.orderId)
+ print(f"Order cancelled: {cancel_status}")
+ except Exception as e:
+ print(f"Error with order operations: {e}")
+
+ # Get positions
+ try:
+ positions = tws.get_positions()
+ print(f"Positions: {positions}")
+ except Exception as e:
+ print(f"Error getting positions: {e}")
+
+finally:
+ # Disconnect
+ print("Disconnecting...")
+ tws.disconnect_and_stop()
+ print("Disconnected")
diff --git a/packages/ibkr/ref/source/ProtoBuf_readme.txt b/packages/ibkr/ref/source/ProtoBuf_readme.txt
new file mode 100644
index 00000000..17f54930
--- /dev/null
+++ b/packages/ibkr/ref/source/ProtoBuf_readme.txt
@@ -0,0 +1,80 @@
+=============================================================================================
+Google Protocol Buffers support in TWS API
+=============================================================================================
+
+Protocol Buffers files are generated with certain proto compiler version. These version numbers are listed below.
+It is customer responsibility to generate proto files if installed proto compiler version doesn't match with version of provided proto files.
+More about Protocol Buffers versions support: https://protobuf.dev/support/version-support/
+To support protobuf the following new software is required:
+
+
+---------------------------------------------------------------------------------------------
+ Java
+---------------------------------------------------------------------------------------------
+Protobuf Java version 4.29.5. Jar required: protobuf-java-4.29.5.jar - this jar is located in source\javaclient\jars
+Latest version can be downloaded from "https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java" to include to Java API project.
+To generate Java proto file, goto "source" directory and run:
+ protoc --proto_path=./proto --java_out=./javaclient proto/*.proto
+
+
+---------------------------------------------------------------------------------------------
+C++
+---------------------------------------------------------------------------------------------
+Protobuf C++ version 5.29.5 (Windows)
+Protobuf C++ version 3.12.4 (Linux)
+
+Windows: to build and run C++ application under Windows the following software is required: Microsoft vcpkg, Protobuf C++ library
+To install the above run the following commands:
+ goto c:\
+ git clone https://github.com/Microsoft/vcpkg.git
+ cd vcpkg
+ bootstrap-vcpkg.bat
+ vcpkg integrate install
+ vcpkg install protobuf
+ vcpkg list
+
+"Protobuf C++ library" for MS Visual Studio can be downloaded from: https://vcpkg.io/en/package/protobuf.html (This site is owned and maintained by Microsoft Corp)
+Vcpkg details are here: https://devblogs.microsoft.com/cppblog/vcpkg-is-now-included-with-visual-studio/
+
+To generate C++ proto file for Windows, goto "source" directory and run:
+ protoc --proto_path=./proto --cpp_out=./cppclient/client/protobuf proto/*.proto
+
+Linux: to build and run C++ application under Linux the following software is required: Protobuf for Linux library
+To install the above run the following commands:
+ apt-get install protobuf-compiler
+
+"Protobuf for Linux" library installation details are here: https://protobuf.dev/installation/)
+
+To generate C++ proto file for Linux, goto "source" directory and run:
+ protoc --proto_path=./proto --experimental_allow_proto3_optional --cpp_out=./cppclient/client/protobufUnix proto/*.proto
+
+
+---------------------------------------------------------------------------------------------
+C#
+---------------------------------------------------------------------------------------------
+Protobuf C#(.NET) version 3.29.5
+
+The following software is required: Google.Protobuf package for .NET
+To install the above do the following:
+ in Visual Studio run NuGet PM: Tools -> NuGet Package Manager -> Package Manager Console
+ in console run: Install-Package Google.Protobuf
+
+"Google.Protobuf package for .NET" can be installed from https://nuget.org/packages/google.protobuf/ (This site is owned and maintained by Microsoft Corp)
+
+To generate C# proto file, goto "source" directory and run:
+ protoc --proto_path=./proto --csharp_out=./csharpclient/client/protobuf proto/*.proto
+
+
+---------------------------------------------------------------------------------------------
+Python
+---------------------------------------------------------------------------------------------
+Protobuf Python version 5.29.5
+
+To run Python application locally the following is required: Protobuf for Python library
+To install the above run the following commands:
+ pip install protobuf
+
+To generate Python proto file, goto "source" directory and run:
+ protoc --proto_path=./proto --python_out=./pythonclient/ibapi/protobuf proto/*.proto
+
+
diff --git a/packages/ibkr/ref/source/proto/AccountDataEnd.proto b/packages/ibkr/ref/source/proto/AccountDataEnd.proto
new file mode 100644
index 00000000..f03c74fe
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountDataEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountDataEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountDataEnd {
+ optional string accountName = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountDataRequest.proto b/packages/ibkr/ref/source/proto/AccountDataRequest.proto
new file mode 100644
index 00000000..c8ffc241
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountDataRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountDataRequest {
+ optional bool subscribe = 1;
+ optional string acctCode = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountSummary.proto b/packages/ibkr/ref/source/proto/AccountSummary.proto
new file mode 100644
index 00000000..a3890049
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountSummary.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountSummaryProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountSummary {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional string tag = 3;
+ optional string value = 4;
+ optional string currency = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountSummaryEnd.proto b/packages/ibkr/ref/source/proto/AccountSummaryEnd.proto
new file mode 100644
index 00000000..300d4da1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountSummaryEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountSummaryEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountSummaryEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountSummaryRequest.proto b/packages/ibkr/ref/source/proto/AccountSummaryRequest.proto
new file mode 100644
index 00000000..7f4e2b1f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountSummaryRequest.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountSummaryRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountSummaryRequest {
+ optional int32 reqId = 1;
+ optional string group = 2;
+ optional string tags = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountUpdateMulti.proto b/packages/ibkr/ref/source/proto/AccountUpdateMulti.proto
new file mode 100644
index 00000000..e803641f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountUpdateMulti.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountUpdateMultiProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountUpdateMulti {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional string modelCode = 3;
+ optional string key = 4;
+ optional string value = 5;
+ optional string currency = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountUpdateMultiEnd.proto b/packages/ibkr/ref/source/proto/AccountUpdateMultiEnd.proto
new file mode 100644
index 00000000..ec613304
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountUpdateMultiEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountUpdateMultiEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountUpdateMultiEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountUpdateTime.proto b/packages/ibkr/ref/source/proto/AccountUpdateTime.proto
new file mode 100644
index 00000000..061b8b6a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountUpdateTime.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountUpdateTimeProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountUpdateTime {
+ optional string timeStamp = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountUpdatesMultiRequest.proto b/packages/ibkr/ref/source/proto/AccountUpdatesMultiRequest.proto
new file mode 100644
index 00000000..321bcb03
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountUpdatesMultiRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountUpdatesMultiRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountUpdatesMultiRequest {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional string modelCode = 3;
+ optional bool ledgerAndNLV = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/AccountValue.proto b/packages/ibkr/ref/source/proto/AccountValue.proto
new file mode 100644
index 00000000..fe5c27d1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AccountValue.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AccountValueProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AccountValue {
+ optional string key = 1;
+ optional string value = 2;
+ optional string currency = 3;
+ optional string accountName = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/AllOpenOrdersRequest.proto b/packages/ibkr/ref/source/proto/AllOpenOrdersRequest.proto
new file mode 100644
index 00000000..8244658d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AllOpenOrdersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AllOpenOrdersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AllOpenOrdersRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/ApiConfig.proto b/packages/ibkr/ref/source/proto/ApiConfig.proto
new file mode 100644
index 00000000..e389a2e6
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ApiConfig.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "ApiPrecautionsConfig.proto";
+import "ApiSettingsConfig.proto";
+
+option java_outer_classname = "ApiConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ApiConfig {
+ optional ApiPrecautionsConfig precautions = 1;
+ optional ApiSettingsConfig settings = 2;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/ApiPrecautionsConfig.proto b/packages/ibkr/ref/source/proto/ApiPrecautionsConfig.proto
new file mode 100644
index 00000000..cb8cee8b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ApiPrecautionsConfig.proto
@@ -0,0 +1,23 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ApiPrecautionsConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ApiPrecautionsConfig {
+ optional bool bypassOrderPrecautions = 1;
+ optional bool bypassBondWarning = 2;
+ optional bool bypassNegativeYieldConfirmation = 3;
+ optional bool bypassCalledBondWarning = 4;
+ optional bool bypassSameActionPairTradeWarning = 5;
+ optional bool bypassFlaggedAccountsWarning = 6;
+ optional bool bypassPriceBasedVolatilityWarning = 7;
+ optional bool bypassRedirectOrderWarning = 8;
+ optional bool bypassNoOverfillProtection = 9;
+ optional bool bypassRouteMarketableToBBO = 10;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/ApiSettingsConfig.proto b/packages/ibkr/ref/source/proto/ApiSettingsConfig.proto
new file mode 100644
index 00000000..04757c83
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ApiSettingsConfig.proto
@@ -0,0 +1,49 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ApiSettingsConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ApiSettingsConfig {
+ optional bool readOnlyApi = 1;
+ optional bool totalQuantityForMutualFunds = 2;
+ optional bool downloadOpenOrdersOnConnection = 3;
+ optional bool includeVirtualFxPositions = 4;
+ optional bool prepareDailyPnL = 5;
+ optional bool sendStatusUpdatesForVolatilityOrders = 6;
+ optional string encodeApiMessages = 7;
+ optional int32 socketPort = 8;
+ optional bool useNegativeAutoRange = 9;
+ optional bool createApiMessageLogFile = 10;
+ optional bool includeMarketDataInLogFile = 11;
+ optional bool exposeTradingScheduleToApi = 12;
+ optional bool splitInsuredDepositFromCashBalance = 13;
+ optional bool sendZeroPositionsForTodayOnly = 14;
+ optional bool letApiAccountRequestsSwitchSubscription = 15;
+ optional bool useAccountGroupsWithAllocationMethods = 16;
+ optional string loggingLevel = 17;
+ optional int32 masterClientId = 18;
+ optional int32 bulkDataTimeout = 19;
+ optional string componentExchSeparator = 20;
+ optional bool showForexDataIn1_10Pips = 21;
+ optional bool allowForexTradingIn1_10Pips = 22;
+ optional bool roundAccountValuesToNearestWholeNumber = 23;
+ optional bool sendMarketDataInLotsForUsStocks = 24;
+ optional bool showAdvancedOrderRejectInUi = 25;
+ optional bool rejectMessagesAboveMaxRate = 26;
+ optional bool maintainConnectionOnIncorrectFields = 27;
+ optional bool compatibilityModeNasdaqStocks = 28;
+ optional string sendInstrumentTimezone = 29;
+ optional bool sendForexDataInCompatibilityMode = 30;
+ optional bool maintainAndResubmitOrdersOnReconnect = 31;
+ optional int32 historicalDataMaxSize = 32;
+ optional bool autoReportNettingEventContractTrades = 33;
+ optional string optionExerciseRequestType = 34;
+ optional bool allowLocalhostOnly = 35;
+ repeated string trustedIPs = 36;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/AttachedOrders.proto b/packages/ibkr/ref/source/proto/AttachedOrders.proto
new file mode 100644
index 00000000..88ca2937
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AttachedOrders.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AttachedOrdersProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AttachedOrders {
+ optional int32 slOrderId = 1;
+ optional string slOrderType = 2;
+ optional int32 ptOrderId = 3;
+ optional string ptOrderType = 4;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/AutoOpenOrdersRequest.proto b/packages/ibkr/ref/source/proto/AutoOpenOrdersRequest.proto
new file mode 100644
index 00000000..a904f0b3
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/AutoOpenOrdersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "AutoOpenOrdersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message AutoOpenOrdersRequest {
+ optional bool autoBind = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CalculateImpliedVolatilityRequest.proto b/packages/ibkr/ref/source/proto/CalculateImpliedVolatilityRequest.proto
new file mode 100644
index 00000000..9d411e2b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CalculateImpliedVolatilityRequest.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "CalculateImpliedVolatilityRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CalculateImpliedVolatilityRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional double optionPrice = 3;
+ optional double underPrice = 4;
+ map impliedVolatilityOptions = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/CalculateOptionPriceRequest.proto b/packages/ibkr/ref/source/proto/CalculateOptionPriceRequest.proto
new file mode 100644
index 00000000..42343ffe
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CalculateOptionPriceRequest.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "CalculateOptionPriceRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CalculateOptionPriceRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional double volatility = 3;
+ optional double underPrice = 4;
+ map optionPriceOptions = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelAccountSummary.proto b/packages/ibkr/ref/source/proto/CancelAccountSummary.proto
new file mode 100644
index 00000000..3437d1bc
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelAccountSummary.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelAccountSummaryProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelAccountSummary {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelAccountUpdatesMulti.proto b/packages/ibkr/ref/source/proto/CancelAccountUpdatesMulti.proto
new file mode 100644
index 00000000..374cc754
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelAccountUpdatesMulti.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelAccountUpdatesMultiProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelAccountUpdatesMulti {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelCalculateImpliedVolatility.proto b/packages/ibkr/ref/source/proto/CancelCalculateImpliedVolatility.proto
new file mode 100644
index 00000000..7094d5e7
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelCalculateImpliedVolatility.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelCalculateImpliedVolatilityProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelCalculateImpliedVolatility {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelCalculateOptionPrice.proto b/packages/ibkr/ref/source/proto/CancelCalculateOptionPrice.proto
new file mode 100644
index 00000000..2a4b0341
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelCalculateOptionPrice.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelCalculateOptionPriceProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelCalculateOptionPrice {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelContractData.proto b/packages/ibkr/ref/source/proto/CancelContractData.proto
new file mode 100644
index 00000000..34469b01
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelContractData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelContractDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelContractData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelFundamentalsData.proto b/packages/ibkr/ref/source/proto/CancelFundamentalsData.proto
new file mode 100644
index 00000000..241cfbfd
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelFundamentalsData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelFundamentalsDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelFundamentalsData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelHeadTimestamp.proto b/packages/ibkr/ref/source/proto/CancelHeadTimestamp.proto
new file mode 100644
index 00000000..dafc2cc0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelHeadTimestamp.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelHeadTimestampProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelHeadTimestamp {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelHistogramData.proto b/packages/ibkr/ref/source/proto/CancelHistogramData.proto
new file mode 100644
index 00000000..e77f5bce
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelHistogramData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelHistogramDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelHistogramData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelHistoricalData.proto b/packages/ibkr/ref/source/proto/CancelHistoricalData.proto
new file mode 100644
index 00000000..5b9d8de0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelHistoricalData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelHistoricalDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelHistoricalData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelHistoricalTicks.proto b/packages/ibkr/ref/source/proto/CancelHistoricalTicks.proto
new file mode 100644
index 00000000..bfb47a60
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelHistoricalTicks.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelHistoricalTicksProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelHistoricalTicks {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelMarketData.proto b/packages/ibkr/ref/source/proto/CancelMarketData.proto
new file mode 100644
index 00000000..bb834887
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelMarketData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelMarketDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelMarketData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelMarketDepth.proto b/packages/ibkr/ref/source/proto/CancelMarketDepth.proto
new file mode 100644
index 00000000..32ea9182
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelMarketDepth.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelMarketDepthProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelMarketDepth {
+ optional int32 reqId = 1;
+ optional bool isSmartDepth = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelNewsBulletins.proto b/packages/ibkr/ref/source/proto/CancelNewsBulletins.proto
new file mode 100644
index 00000000..3d5d7871
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelNewsBulletins.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelNewsBulletinsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelNewsBulletins {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/CancelOrderRequest.proto b/packages/ibkr/ref/source/proto/CancelOrderRequest.proto
new file mode 100644
index 00000000..54ef99c0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelOrderRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "OrderCancel.proto";
+
+option java_outer_classname = "CancelOrderRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelOrderRequest {
+ optional int32 orderId = 1;
+ optional OrderCancel orderCancel = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelPnL.proto b/packages/ibkr/ref/source/proto/CancelPnL.proto
new file mode 100644
index 00000000..39505686
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelPnL.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelPnLProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelPnL {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelPnLSingle.proto b/packages/ibkr/ref/source/proto/CancelPnLSingle.proto
new file mode 100644
index 00000000..de695ecf
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelPnLSingle.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelPnLSingleProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelPnLSingle {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelPositions.proto b/packages/ibkr/ref/source/proto/CancelPositions.proto
new file mode 100644
index 00000000..825d6676
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelPositions.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelPositionsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelPositions {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/CancelPositionsMulti.proto b/packages/ibkr/ref/source/proto/CancelPositionsMulti.proto
new file mode 100644
index 00000000..2dd4642b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelPositionsMulti.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelPositionsMultiProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelPositionsMulti {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelRealTimeBars.proto b/packages/ibkr/ref/source/proto/CancelRealTimeBars.proto
new file mode 100644
index 00000000..17254485
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelRealTimeBars.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelRealTimeBarsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelRealTimeBars {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelScannerSubscription.proto b/packages/ibkr/ref/source/proto/CancelScannerSubscription.proto
new file mode 100644
index 00000000..3f14ddf4
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelScannerSubscription.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelScannerSubscriptionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelScannerSubscription {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelTickByTick.proto b/packages/ibkr/ref/source/proto/CancelTickByTick.proto
new file mode 100644
index 00000000..fbad4b35
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelTickByTick.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelTickByTickProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelTickByTick {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelWshEventData.proto b/packages/ibkr/ref/source/proto/CancelWshEventData.proto
new file mode 100644
index 00000000..5ffe608c
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelWshEventData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelWshEventDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelWshEventData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CancelWshMetaData.proto b/packages/ibkr/ref/source/proto/CancelWshMetaData.proto
new file mode 100644
index 00000000..8a8b053f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CancelWshMetaData.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CancelWshMetaDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CancelWshMetaData {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/ComboLeg.proto b/packages/ibkr/ref/source/proto/ComboLeg.proto
new file mode 100644
index 00000000..176ceca0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ComboLeg.proto
@@ -0,0 +1,22 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ComboLegProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ComboLeg {
+ optional int32 conId = 1;
+ optional int32 ratio = 2;
+ optional string action = 3;
+ optional string exchange = 4;
+ optional int32 openClose = 5;
+ optional int32 shortSalesSlot = 6;
+ optional string designatedLocation = 7;
+ optional int32 exemptCode = 8;
+ optional double perLegPrice = 9;
+}
diff --git a/packages/ibkr/ref/source/proto/CommissionAndFeesReport.proto b/packages/ibkr/ref/source/proto/CommissionAndFeesReport.proto
new file mode 100644
index 00000000..99fcec22
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CommissionAndFeesReport.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CommissionAndFeesReportProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CommissionAndFeesReport {
+ optional string execId = 1;
+ optional double commissionAndFees = 2;
+ optional string currency = 3;
+ optional double realizedPNL = 4;
+ optional double bondYield = 5;
+ optional string yieldRedemptionDate = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/CompletedOrder.proto b/packages/ibkr/ref/source/proto/CompletedOrder.proto
new file mode 100644
index 00000000..a073be31
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CompletedOrder.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+import "Order.proto";
+import "OrderState.proto";
+
+option java_outer_classname = "CompletedOrderProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CompletedOrder {
+ optional Contract contract = 1;
+ optional Order order = 2;
+ optional OrderState orderState = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/CompletedOrdersEnd.proto b/packages/ibkr/ref/source/proto/CompletedOrdersEnd.proto
new file mode 100644
index 00000000..060a8d13
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CompletedOrdersEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CompletedOrdersEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CompletedOrdersEnd {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/CompletedOrdersRequest.proto b/packages/ibkr/ref/source/proto/CompletedOrdersRequest.proto
new file mode 100644
index 00000000..f12c38d3
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CompletedOrdersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CompletedOrdersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CompletedOrdersRequest {
+ optional bool apiOnly = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/ConfigRequest.proto b/packages/ibkr/ref/source/proto/ConfigRequest.proto
new file mode 100644
index 00000000..b001457d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ConfigRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ConfigRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ConfigRequest {
+ optional int32 reqId = 1;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/ConfigResponse.proto b/packages/ibkr/ref/source/proto/ConfigResponse.proto
new file mode 100644
index 00000000..7d07f43a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ConfigResponse.proto
@@ -0,0 +1,23 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "LockAndExitConfig.proto";
+import "MessageConfig.proto";
+import "ApiConfig.proto";
+import "OrdersConfig.proto";
+
+option java_outer_classname = "ConfigResponseProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ConfigResponse {
+ optional int32 reqId = 1;
+ optional LockAndExitConfig lockAndExit = 2;
+ repeated MessageConfig messages = 3;
+ optional ApiConfig api = 4;
+ optional OrdersConfig orders = 5;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/Contract.proto b/packages/ibkr/ref/source/proto/Contract.proto
new file mode 100644
index 00000000..051e4199
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/Contract.proto
@@ -0,0 +1,37 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "ComboLeg.proto";
+import "DeltaNeutralContract.proto";
+
+option java_outer_classname = "ContractProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message Contract {
+ optional int32 conId = 1;
+ optional string symbol = 2;
+ optional string secType = 3;
+ optional string lastTradeDateOrContractMonth = 4;
+ optional double strike = 5;
+ optional string right = 6;
+ optional double multiplier = 7;
+ optional string exchange = 8;
+ optional string primaryExch = 9;
+ optional string currency = 10;
+ optional string localSymbol = 11;
+ optional string tradingClass = 12;
+ optional string secIdType = 13;
+ optional string secId = 14;
+ optional string description = 15;
+ optional string issuerId = 16;
+ optional DeltaNeutralContract deltaNeutralContract = 17;
+ optional bool includeExpired = 18;
+ optional string comboLegsDescrip = 19;
+ repeated ComboLeg comboLegs = 20;
+ optional string lastTradeDate = 21;
+}
diff --git a/packages/ibkr/ref/source/proto/ContractData.proto b/packages/ibkr/ref/source/proto/ContractData.proto
new file mode 100644
index 00000000..ebbe70fa
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ContractData.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+import "ContractDetails.proto";
+
+option java_outer_classname = "ContractDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ContractData {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional ContractDetails contractDetails = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/ContractDataEnd.proto b/packages/ibkr/ref/source/proto/ContractDataEnd.proto
new file mode 100644
index 00000000..0ef6d7ee
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ContractDataEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ContractDataEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ContractDataEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/ContractDataRequest.proto b/packages/ibkr/ref/source/proto/ContractDataRequest.proto
new file mode 100644
index 00000000..9bf1c388
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ContractDataRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "ContractDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ContractDataRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/ContractDescription.proto b/packages/ibkr/ref/source/proto/ContractDescription.proto
new file mode 100644
index 00000000..722f34bb
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ContractDescription.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "ContractDescriptionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ContractDescription {
+ optional Contract contract = 1;
+ repeated string derivativeSecTypes = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/ContractDetails.proto b/packages/ibkr/ref/source/proto/ContractDetails.proto
new file mode 100644
index 00000000..82054096
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ContractDetails.proto
@@ -0,0 +1,87 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "IneligibilityReason.proto";
+
+option java_outer_classname = "ContractDetailsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ContractDetails {
+ optional string marketName = 1;
+ optional string minTick = 2;
+ optional string orderTypes = 3;
+ optional string validExchanges = 4;
+ optional int32 priceMagnifier = 5;
+ optional int32 underConId = 6;
+ optional string longName = 7;
+ optional string contractMonth = 8;
+ optional string industry = 9;
+ optional string category = 10;
+ optional string subcategory = 11;
+ optional string timeZoneId = 12;
+ optional string tradingHours = 13;
+ optional string liquidHours = 14;
+ optional string evRule = 15;
+ optional double evMultiplier = 16;
+ map secIdList = 17;
+ optional int32 aggGroup = 18;
+ optional string underSymbol = 19;
+ optional string underSecType = 20;
+ optional string marketRuleIds = 21;
+ optional string realExpirationDate = 22;
+ optional string stockType = 23;
+ optional string minSize = 24;
+ optional string sizeIncrement = 25;
+ optional string suggestedSizeIncrement = 26;
+
+ // fund fields
+ optional string fundName = 27;
+ optional string fundFamily = 28;
+ optional string fundType = 29;
+ optional string fundFrontLoad = 30;
+ optional string fundBackLoad = 31;
+ optional string fundBackLoadTimeInterval = 32;
+ optional string fundManagementFee = 33;
+ optional bool fundClosed = 34;
+ optional bool fundClosedForNewInvestors = 35;
+ optional bool fundClosedForNewMoney = 36;
+ optional string fundNotifyAmount = 37;
+ optional string fundMinimumInitialPurchase = 38;
+ optional string fundMinimumSubsequentPurchase = 39;
+ optional string fundBlueSkyStates = 40;
+ optional string fundBlueSkyTerritories = 41;
+ optional string fundDistributionPolicyIndicator = 42;
+ optional string fundAssetType = 43;
+
+ // bond fields
+ optional string cusip = 44;
+ optional string issueDate = 45;
+ optional string ratings = 46;
+ optional string bondType = 47;
+ optional double coupon = 48;
+ optional string couponType = 49;
+ optional bool convertible = 50;
+ optional bool callable = 51;
+ optional bool puttable = 52;
+ optional string descAppend = 53;
+ optional string nextOptionDate = 54;
+ optional string nextOptionType = 55;
+ optional bool nextOptionPartial = 56;
+ optional string bondNotes = 57;
+
+ repeated IneligibilityReason ineligibilityReasonList = 58;
+
+ // event contract fields
+ optional string eventContract1 = 59;
+ optional string eventContractDescription1 = 60;
+ optional string eventContractDescription2 = 61;
+
+ optional string minAlgoSize = 62;
+ optional string lastPricePrecision = 63;
+ optional string lastSizePrecision = 64;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/CurrentTime.proto b/packages/ibkr/ref/source/proto/CurrentTime.proto
new file mode 100644
index 00000000..1f97e9bf
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CurrentTime.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CurrentTimeProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CurrentTime {
+ optional int64 currentTime = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CurrentTimeInMillis.proto b/packages/ibkr/ref/source/proto/CurrentTimeInMillis.proto
new file mode 100644
index 00000000..e56d0a53
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CurrentTimeInMillis.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CurrentTimeInMillisProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CurrentTimeInMillis {
+ optional int64 currentTimeInMillis = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/CurrentTimeInMillisRequest.proto b/packages/ibkr/ref/source/proto/CurrentTimeInMillisRequest.proto
new file mode 100644
index 00000000..875c8792
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CurrentTimeInMillisRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CurrentTimeInMillisRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CurrentTimeInMillisRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/CurrentTimeRequest.proto b/packages/ibkr/ref/source/proto/CurrentTimeRequest.proto
new file mode 100644
index 00000000..013cbf0b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/CurrentTimeRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "CurrentTimeRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message CurrentTimeRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/DeltaNeutralContract.proto b/packages/ibkr/ref/source/proto/DeltaNeutralContract.proto
new file mode 100644
index 00000000..4fcbda58
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/DeltaNeutralContract.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "DeltaNeutralContractProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message DeltaNeutralContract {
+ optional int32 conId = 1;
+ optional double delta = 2;
+ optional double price = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/DepthMarketDataDescription.proto b/packages/ibkr/ref/source/proto/DepthMarketDataDescription.proto
new file mode 100644
index 00000000..1f6d2ee7
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/DepthMarketDataDescription.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "DepthMarketDataDescriptionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message DepthMarketDataDescription {
+ optional string exchange = 1;
+ optional string secType = 2;
+ optional string listingExch = 3;
+ optional string serviceDataType = 4;
+ optional int32 aggGroup = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/DisplayGroupList.proto b/packages/ibkr/ref/source/proto/DisplayGroupList.proto
new file mode 100644
index 00000000..f70ee4e3
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/DisplayGroupList.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "DisplayGroupListProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message DisplayGroupList {
+ optional int32 reqId = 1;
+ optional string groups = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/DisplayGroupUpdated.proto b/packages/ibkr/ref/source/proto/DisplayGroupUpdated.proto
new file mode 100644
index 00000000..d66c4c48
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/DisplayGroupUpdated.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "DisplayGroupUpdatedProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message DisplayGroupUpdated {
+ optional int32 reqId = 1;
+ optional string contractInfo = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/ErrorMessage.proto b/packages/ibkr/ref/source/proto/ErrorMessage.proto
new file mode 100644
index 00000000..c7dcf77b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ErrorMessage.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ErrorMessageProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ErrorMessage {
+ optional int32 id = 1;
+ optional int64 errorTime = 2;
+ optional int32 errorCode = 3;
+ optional string errorMsg = 4;
+ optional string advancedOrderRejectJson = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/Execution.proto b/packages/ibkr/ref/source/proto/Execution.proto
new file mode 100644
index 00000000..d66551cf
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/Execution.proto
@@ -0,0 +1,34 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ExecutionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message Execution {
+ optional int32 orderId = 1;
+ optional string execId = 2;
+ optional string time = 3;
+ optional string acctNumber = 4;
+ optional string exchange = 5;
+ optional string side = 6;
+ optional string shares = 7;
+ optional double price = 8;
+ optional int64 permId = 9;
+ optional int32 clientId = 10;
+ optional bool isLiquidation = 11;
+ optional string cumQty = 12;
+ optional double avgPrice = 13;
+ optional string orderRef = 14;
+ optional string evRule = 15;
+ optional double evMultiplier = 16;
+ optional string modelCode = 17;
+ optional int32 lastLiquidity = 18;
+ optional bool isPriceRevisionPending = 19;
+ optional string submitter = 20;
+ optional int32 optExerciseOrLapseType = 21;
+}
diff --git a/packages/ibkr/ref/source/proto/ExecutionDetails.proto b/packages/ibkr/ref/source/proto/ExecutionDetails.proto
new file mode 100644
index 00000000..aaec8637
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ExecutionDetails.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+import "Execution.proto";
+
+option java_outer_classname = "ExecutionDetailsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ExecutionDetails {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional Execution execution = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/ExecutionDetailsEnd.proto b/packages/ibkr/ref/source/proto/ExecutionDetailsEnd.proto
new file mode 100644
index 00000000..9dd2b4ad
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ExecutionDetailsEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ExecutionDetailsEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ExecutionDetailsEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/ExecutionFilter.proto b/packages/ibkr/ref/source/proto/ExecutionFilter.proto
new file mode 100644
index 00000000..d519ec22
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ExecutionFilter.proto
@@ -0,0 +1,22 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ExecutionFilterProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ExecutionFilter {
+ optional int32 clientId = 1;
+ optional string acctCode = 2;
+ optional string time = 3;
+ optional string symbol = 4;
+ optional string secType = 5;
+ optional string exchange = 6;
+ optional string side = 7;
+ optional int32 lastNDays = 8;
+ repeated int32 specificDates = 9;
+}
diff --git a/packages/ibkr/ref/source/proto/ExecutionRequest.proto b/packages/ibkr/ref/source/proto/ExecutionRequest.proto
new file mode 100644
index 00000000..51bdd5b9
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ExecutionRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "ExecutionFilter.proto";
+
+option java_outer_classname = "ExecutionRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ExecutionRequest {
+ optional int32 reqId = 1;
+ optional ExecutionFilter executionFilter = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/ExerciseOptionsRequest.proto b/packages/ibkr/ref/source/proto/ExerciseOptionsRequest.proto
new file mode 100644
index 00000000..f2210758
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ExerciseOptionsRequest.proto
@@ -0,0 +1,24 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "ExerciseOptionsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ExerciseOptionsRequest {
+ optional int32 orderId = 1;
+ optional Contract contract = 2;
+ optional int32 exerciseAction = 3;
+ optional int32 exerciseQuantity = 4;
+ optional string account = 5;
+ optional bool override = 6;
+ optional string manualOrderTime = 7;
+ optional string customerAccount = 8;
+ optional bool professionalCustomer = 9;
+}
diff --git a/packages/ibkr/ref/source/proto/FAReplace.proto b/packages/ibkr/ref/source/proto/FAReplace.proto
new file mode 100644
index 00000000..7a1e354d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FAReplace.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "FAReplaceProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FAReplace {
+ optional int32 reqId = 1;
+ optional int32 faDataType = 2;
+ optional string xml = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/FARequest.proto b/packages/ibkr/ref/source/proto/FARequest.proto
new file mode 100644
index 00000000..2c6c5f38
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FARequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "FARequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FARequest {
+ optional int32 faDataType = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/FamilyCode.proto b/packages/ibkr/ref/source/proto/FamilyCode.proto
new file mode 100644
index 00000000..09616cc6
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FamilyCode.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "FamilyCodeProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FamilyCode {
+ optional string accountId = 1;
+ optional string familyCode = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/FamilyCodes.proto b/packages/ibkr/ref/source/proto/FamilyCodes.proto
new file mode 100644
index 00000000..aa2de56d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FamilyCodes.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "FamilyCode.proto";
+
+option java_outer_classname = "FamilyCodesProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FamilyCodes {
+ repeated FamilyCode familyCodes = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/FamilyCodesRequest.proto b/packages/ibkr/ref/source/proto/FamilyCodesRequest.proto
new file mode 100644
index 00000000..d8987cf5
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FamilyCodesRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "FamilyCodesRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FamilyCodesRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/FundamentalsData.proto b/packages/ibkr/ref/source/proto/FundamentalsData.proto
new file mode 100644
index 00000000..7a8bf01e
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FundamentalsData.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "FundamentalsDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FundamentalsData {
+ optional int32 reqId = 1;
+ optional string data = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/FundamentalsDataRequest.proto b/packages/ibkr/ref/source/proto/FundamentalsDataRequest.proto
new file mode 100644
index 00000000..7e3fe48c
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/FundamentalsDataRequest.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "FundamentalsDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message FundamentalsDataRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional string reportType = 3;
+ map fundamentalsDataOptions = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/GlobalCancelRequest.proto b/packages/ibkr/ref/source/proto/GlobalCancelRequest.proto
new file mode 100644
index 00000000..a8722ec7
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/GlobalCancelRequest.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "OrderCancel.proto";
+
+option java_outer_classname = "GlobalCancelRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message GlobalCancelRequest {
+ optional OrderCancel orderCancel = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/HeadTimestamp.proto b/packages/ibkr/ref/source/proto/HeadTimestamp.proto
new file mode 100644
index 00000000..6f609e76
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HeadTimestamp.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HeadTimestampProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HeadTimestamp {
+ optional int32 reqId = 1;
+ optional string headTimestamp = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/HeadTimestampRequest.proto b/packages/ibkr/ref/source/proto/HeadTimestampRequest.proto
new file mode 100644
index 00000000..7c4f996a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HeadTimestampRequest.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "HeadTimestampRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HeadTimestampRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional bool useRTH = 3;
+ optional string whatToShow = 4;
+ optional int32 formatDate = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/HistogramData.proto b/packages/ibkr/ref/source/proto/HistogramData.proto
new file mode 100644
index 00000000..31d87b08
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistogramData.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistogramDataEntry.proto";
+
+option java_outer_classname = "HistogramDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistogramData {
+ optional int32 reqId = 1;
+ repeated HistogramDataEntry histogramDataEntries = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/HistogramDataEntry.proto b/packages/ibkr/ref/source/proto/HistogramDataEntry.proto
new file mode 100644
index 00000000..bd1495c9
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistogramDataEntry.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistogramDataEntryProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistogramDataEntry {
+ optional double price = 1;
+ optional string size = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/HistogramDataRequest.proto b/packages/ibkr/ref/source/proto/HistogramDataRequest.proto
new file mode 100644
index 00000000..36e97b54
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistogramDataRequest.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "HistogramDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistogramDataRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional bool useRTH = 3;
+ optional string timePeriod = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalData.proto b/packages/ibkr/ref/source/proto/HistoricalData.proto
new file mode 100644
index 00000000..fad01871
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalData.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalDataBar.proto";
+
+option java_outer_classname = "HistoricalDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalData {
+ optional int32 reqId = 1;
+ repeated HistoricalDataBar historicalDataBars = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalDataBar.proto b/packages/ibkr/ref/source/proto/HistoricalDataBar.proto
new file mode 100644
index 00000000..4b7bd3d2
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalDataBar.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalDataBarProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalDataBar {
+ optional string date = 1;
+ optional double open = 2;
+ optional double high = 3;
+ optional double low = 4;
+ optional double close = 5;
+ optional string volume = 6;
+ optional string WAP = 7;
+ optional int32 barCount = 8;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalDataEnd.proto b/packages/ibkr/ref/source/proto/HistoricalDataEnd.proto
new file mode 100644
index 00000000..c7a021e1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalDataEnd.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalDataEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalDataEnd {
+ optional int32 reqId = 1;
+ optional string startDateStr = 2;
+ optional string endDateStr = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalDataRequest.proto b/packages/ibkr/ref/source/proto/HistoricalDataRequest.proto
new file mode 100644
index 00000000..3f49a939
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalDataRequest.proto
@@ -0,0 +1,25 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "HistoricalDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalDataRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional string endDateTime = 3;
+ optional string barSizeSetting = 4;
+ optional string duration = 5;
+ optional bool useRTH = 6;
+ optional string whatToShow = 7;
+ optional int32 formatDate = 8;
+ optional bool keepUpToDate = 9;
+ map chartOptions = 10;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalDataUpdate.proto b/packages/ibkr/ref/source/proto/HistoricalDataUpdate.proto
new file mode 100644
index 00000000..c6da14eb
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalDataUpdate.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalDataBar.proto";
+
+option java_outer_classname = "HistoricalDataUpdateProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalDataUpdate {
+ optional int32 reqId = 1;
+ optional HistoricalDataBar historicalDataBar = 2;
+}
+
diff --git a/packages/ibkr/ref/source/proto/HistoricalNews.proto b/packages/ibkr/ref/source/proto/HistoricalNews.proto
new file mode 100644
index 00000000..b8bae501
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalNews.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalNewsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalNews {
+ optional int32 reqId = 1;
+ optional string time = 2;
+ optional string providerCode = 3;
+ optional string articleId = 4;
+ optional string headline = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalNewsEnd.proto b/packages/ibkr/ref/source/proto/HistoricalNewsEnd.proto
new file mode 100644
index 00000000..ed608941
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalNewsEnd.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalNewsEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalNewsEnd {
+ optional int32 reqId = 1;
+ optional bool hasMore = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalNewsRequest.proto b/packages/ibkr/ref/source/proto/HistoricalNewsRequest.proto
new file mode 100644
index 00000000..3bfdd46a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalNewsRequest.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalNewsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalNewsRequest {
+ optional int32 reqId = 1;
+ optional int32 conId = 2;
+ optional string providerCodes = 3;
+ optional string startDateTime = 4;
+ optional string endDateTime = 5;
+ optional int32 totalResults = 6;
+ map historicalNewsOptions = 7;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalSchedule.proto b/packages/ibkr/ref/source/proto/HistoricalSchedule.proto
new file mode 100644
index 00000000..0f1470d8
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalSchedule.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalSession.proto";
+
+option java_outer_classname = "HistoricalScheduleProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalSchedule {
+ optional int32 reqId = 1;
+ optional string startDateTime = 2;
+ optional string endDateTime = 3;
+ optional string timeZone = 4;
+ repeated HistoricalSession historicalSessions = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalSession.proto b/packages/ibkr/ref/source/proto/HistoricalSession.proto
new file mode 100644
index 00000000..97ae271d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalSession.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalSessionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalSession {
+ optional string startDateTime = 1;
+ optional string endDateTime = 2;
+ optional string refDate = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTick.proto b/packages/ibkr/ref/source/proto/HistoricalTick.proto
new file mode 100644
index 00000000..35894a3b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTick.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "HistoricalTickProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTick {
+ optional int64 time = 1;
+ optional double price = 2;
+ optional string size = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTickBidAsk.proto b/packages/ibkr/ref/source/proto/HistoricalTickBidAsk.proto
new file mode 100644
index 00000000..77cdad44
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTickBidAsk.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "TickAttribBidAsk.proto";
+
+option java_outer_classname = "HistoricalTickBidAskProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTickBidAsk {
+ optional int64 time = 1;
+ optional TickAttribBidAsk tickAttribBidAsk = 2;
+ optional double priceBid = 3;
+ optional double priceAsk = 4;
+ optional string sizeBid = 5;
+ optional string sizeAsk = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTickLast.proto b/packages/ibkr/ref/source/proto/HistoricalTickLast.proto
new file mode 100644
index 00000000..d02884b7
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTickLast.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "TickAttribLast.proto";
+
+option java_outer_classname = "HistoricalTickLastProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTickLast {
+ optional int64 time = 1;
+ optional TickAttribLast tickAttribLast = 2;
+ optional double price = 3;
+ optional string size = 4;
+ optional string exchange = 5;
+ optional string specialConditions = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTicks.proto b/packages/ibkr/ref/source/proto/HistoricalTicks.proto
new file mode 100644
index 00000000..e300d13f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTicks.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalTick.proto";
+
+option java_outer_classname = "HistoricalTicksProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTicks {
+ optional int32 reqId = 1;
+ repeated HistoricalTick historicalTicks = 2;
+ optional bool isDone = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTicksBidAsk.proto b/packages/ibkr/ref/source/proto/HistoricalTicksBidAsk.proto
new file mode 100644
index 00000000..6eb39fc4
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTicksBidAsk.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalTickBidAsk.proto";
+
+option java_outer_classname = "HistoricalTicksBidAskProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTicksBidAsk {
+ optional int32 reqId = 1;
+ repeated HistoricalTickBidAsk historicalTicksBidAsk = 2;
+ optional bool isDone = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTicksLast.proto b/packages/ibkr/ref/source/proto/HistoricalTicksLast.proto
new file mode 100644
index 00000000..e1fc2886
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTicksLast.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalTickLast.proto";
+
+option java_outer_classname = "HistoricalTicksLastProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTicksLast {
+ optional int32 reqId = 1;
+ repeated HistoricalTickLast historicalTicksLast = 2;
+ optional bool isDone = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/HistoricalTicksRequest.proto b/packages/ibkr/ref/source/proto/HistoricalTicksRequest.proto
new file mode 100644
index 00000000..4de4a87c
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/HistoricalTicksRequest.proto
@@ -0,0 +1,24 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "HistoricalTicksRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message HistoricalTicksRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional string startDateTime = 3;
+ optional string endDateTime = 4;
+ optional int32 numberOfTicks = 5;
+ optional string whatToShow = 6;
+ optional bool useRTH = 7;
+ optional bool ignoreSize = 8;
+ map miscOptions = 9;
+}
diff --git a/packages/ibkr/ref/source/proto/IdsRequest.proto b/packages/ibkr/ref/source/proto/IdsRequest.proto
new file mode 100644
index 00000000..254c6b95
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/IdsRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "IdsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message IdsRequest {
+ optional int32 numIds = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/IneligibilityReason.proto b/packages/ibkr/ref/source/proto/IneligibilityReason.proto
new file mode 100644
index 00000000..f0afe835
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/IneligibilityReason.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "IneligibilityReasonProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message IneligibilityReason {
+ optional string id = 1;
+ optional string description = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/LockAndExitConfig.proto b/packages/ibkr/ref/source/proto/LockAndExitConfig.proto
new file mode 100644
index 00000000..27ccca40
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/LockAndExitConfig.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "LockAndExitConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message LockAndExitConfig {
+ optional string autoLogoffTime = 1;
+ optional string autoLogoffPeriod = 2;
+ optional string autoLogoffType = 3;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/ManagedAccounts.proto b/packages/ibkr/ref/source/proto/ManagedAccounts.proto
new file mode 100644
index 00000000..d6257a4f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ManagedAccounts.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ManagedAccountsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ManagedAccounts {
+ optional string accountsList = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/ManagedAccountsRequest.proto b/packages/ibkr/ref/source/proto/ManagedAccountsRequest.proto
new file mode 100644
index 00000000..a281fda3
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ManagedAccountsRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ManagedAccountsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ManagedAccountsRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDataRequest.proto b/packages/ibkr/ref/source/proto/MarketDataRequest.proto
new file mode 100644
index 00000000..75c48cc8
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDataRequest.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "MarketDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDataRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional string genericTickList = 3;
+ optional bool snapshot = 4;
+ optional bool regulatorySnapshot = 5;
+ map marketDataOptions = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDataType.proto b/packages/ibkr/ref/source/proto/MarketDataType.proto
new file mode 100644
index 00000000..33b63092
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDataType.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MarketDataTypeProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDataType {
+ optional int32 reqId = 1;
+ optional int32 marketDataType = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDataTypeRequest.proto b/packages/ibkr/ref/source/proto/MarketDataTypeRequest.proto
new file mode 100644
index 00000000..5d0614c4
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDataTypeRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MarketDataTypeRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDataTypeRequest {
+ optional int32 marketDataType = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDepth.proto b/packages/ibkr/ref/source/proto/MarketDepth.proto
new file mode 100644
index 00000000..89fd372b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDepth.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "MarketDepthData.proto";
+
+option java_outer_classname = "MarketDepthProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDepth {
+ optional int32 reqId = 1;
+ optional MarketDepthData marketDepthData = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDepthData.proto b/packages/ibkr/ref/source/proto/MarketDepthData.proto
new file mode 100644
index 00000000..057338f9
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDepthData.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MarketDepthDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDepthData {
+ optional int32 position = 1;
+ optional int32 operation = 2;
+ optional int32 side = 3;
+ optional double price = 4;
+ optional string size = 5;
+ optional string marketMaker = 6;
+ optional bool isSmartDepth = 7;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDepthExchanges.proto b/packages/ibkr/ref/source/proto/MarketDepthExchanges.proto
new file mode 100644
index 00000000..26824956
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDepthExchanges.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "DepthMarketDataDescription.proto";
+
+option java_outer_classname = "MarketDepthExchangesProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDepthExchanges {
+ repeated DepthMarketDataDescription depthMarketDataDescriptions = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDepthExchangesRequest.proto b/packages/ibkr/ref/source/proto/MarketDepthExchangesRequest.proto
new file mode 100644
index 00000000..8dd865c6
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDepthExchangesRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MarketDepthExchangesRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDepthExchangesRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDepthL2.proto b/packages/ibkr/ref/source/proto/MarketDepthL2.proto
new file mode 100644
index 00000000..1feadf30
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDepthL2.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "MarketDepthData.proto";
+
+option java_outer_classname = "MarketDepthL2Proto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDepthL2 {
+ optional int32 reqId = 1;
+ optional MarketDepthData marketDepthData = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketDepthRequest.proto b/packages/ibkr/ref/source/proto/MarketDepthRequest.proto
new file mode 100644
index 00000000..67d73c2a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketDepthRequest.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "MarketDepthRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketDepthRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional int32 numRows = 3;
+ optional bool isSmartDepth = 4;
+ map marketDepthOptions = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketRule.proto b/packages/ibkr/ref/source/proto/MarketRule.proto
new file mode 100644
index 00000000..5919b957
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketRule.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "PriceIncrement.proto";
+
+option java_outer_classname = "MarketRuleProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketRule {
+ optional int32 marketRuleId = 1;
+ repeated PriceIncrement priceIncrements = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/MarketRuleRequest.proto b/packages/ibkr/ref/source/proto/MarketRuleRequest.proto
new file mode 100644
index 00000000..93896d2d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MarketRuleRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MarketRuleRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MarketRuleRequest {
+ optional int32 marketRuleId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/MatchingSymbolsRequest.proto b/packages/ibkr/ref/source/proto/MatchingSymbolsRequest.proto
new file mode 100644
index 00000000..94f30ac2
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MatchingSymbolsRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MatchingSymbolsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MatchingSymbolsRequest {
+ optional int32 reqId = 1;
+ optional string pattern = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/MessageConfig.proto b/packages/ibkr/ref/source/proto/MessageConfig.proto
new file mode 100644
index 00000000..f39271d8
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/MessageConfig.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "MessageConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message MessageConfig {
+ optional int32 id = 1;
+ optional string title = 2;
+ optional string message = 3;
+ optional string defaultAction = 4;
+ optional bool enabled = 5;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/NewsArticle.proto b/packages/ibkr/ref/source/proto/NewsArticle.proto
new file mode 100644
index 00000000..f9a023d3
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsArticle.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NewsArticleProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsArticle {
+ optional int32 reqId = 1;
+ optional int32 articleType = 2;
+ optional string articleText = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/NewsArticleRequest.proto b/packages/ibkr/ref/source/proto/NewsArticleRequest.proto
new file mode 100644
index 00000000..bbac9b85
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsArticleRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NewsArticleRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsArticleRequest {
+ optional int32 reqId = 1;
+ optional string providerCode = 2;
+ optional string articleId = 3;
+ map newsArticleOptions = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/NewsBulletin.proto b/packages/ibkr/ref/source/proto/NewsBulletin.proto
new file mode 100644
index 00000000..bd7467de
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsBulletin.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NewsBulletinProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsBulletin {
+ optional int32 newsMsgId = 1;
+ optional int32 newsMsgType = 2;
+ optional string newsMessage = 3;
+ optional string originatingExch = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/NewsBulletinsRequest.proto b/packages/ibkr/ref/source/proto/NewsBulletinsRequest.proto
new file mode 100644
index 00000000..51313f0f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsBulletinsRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NewsBulletinsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsBulletinsRequest {
+ optional bool allMessages = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/NewsProvider.proto b/packages/ibkr/ref/source/proto/NewsProvider.proto
new file mode 100644
index 00000000..ede76aed
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsProvider.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NewsProviderProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsProvider {
+ optional string providerCode = 1;
+ optional string providerName = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/NewsProviders.proto b/packages/ibkr/ref/source/proto/NewsProviders.proto
new file mode 100644
index 00000000..3aa8ddc0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsProviders.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "NewsProvider.proto";
+
+option java_outer_classname = "NewsProvidersProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsProviders {
+ repeated NewsProvider newsProviders = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/NewsProvidersRequest.proto b/packages/ibkr/ref/source/proto/NewsProvidersRequest.proto
new file mode 100644
index 00000000..543de8dd
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NewsProvidersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NewsProvidersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NewsProvidersRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/NextValidId.proto b/packages/ibkr/ref/source/proto/NextValidId.proto
new file mode 100644
index 00000000..5e9be544
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/NextValidId.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "NextValidIdProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message NextValidId {
+ optional int32 orderId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/OpenOrder.proto b/packages/ibkr/ref/source/proto/OpenOrder.proto
new file mode 100644
index 00000000..21504440
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OpenOrder.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+import "Order.proto";
+import "OrderState.proto";
+
+option java_outer_classname = "OpenOrderProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OpenOrder {
+ optional int32 orderId = 1;
+ optional Contract contract = 2;
+ optional Order order = 3;
+ optional OrderState orderState = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/OpenOrdersEnd.proto b/packages/ibkr/ref/source/proto/OpenOrdersEnd.proto
new file mode 100644
index 00000000..ed598297
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OpenOrdersEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OpenOrdersEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OpenOrdersEnd {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/OpenOrdersRequest.proto b/packages/ibkr/ref/source/proto/OpenOrdersRequest.proto
new file mode 100644
index 00000000..c8145a35
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OpenOrdersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OpenOrdersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OpenOrdersRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/Order.proto b/packages/ibkr/ref/source/proto/Order.proto
new file mode 100644
index 00000000..19429175
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/Order.proto
@@ -0,0 +1,213 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "OrderCondition.proto";
+import "SoftDollarTier.proto";
+
+option java_outer_classname = "OrderProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message Order {
+
+ // order ids
+ optional int32 clientId = 1;
+ optional int32 orderId = 2;
+ optional int64 permId = 3;
+ optional int32 parentId = 4;
+
+ // primary attributes
+ optional string action = 5;
+ optional string totalQuantity = 6;
+ optional int32 displaySize = 7;
+ optional string orderType = 8;
+ optional double lmtPrice = 9;
+ optional double auxPrice = 10;
+ optional string tif = 11;
+
+ // clearing info
+ optional string account = 12;
+ optional string settlingFirm = 13;
+ optional string clearingAccount = 14;
+ optional string clearingIntent = 15;
+
+ // secondary attributes
+ optional bool allOrNone = 16;
+ optional bool blockOrder = 17;
+ optional bool hidden = 18;
+ optional bool outsideRth = 19;
+ optional bool sweepToFill = 20;
+ optional double percentOffset = 21;
+ optional double trailingPercent = 22;
+ optional double trailStopPrice = 23;
+ optional int32 minQty = 24;
+ optional string goodAfterTime = 25;
+ optional string goodTillDate = 26;
+ optional string ocaGroup = 27;
+ optional string orderRef = 28;
+ optional string rule80A = 29;
+ optional int32 ocaType = 30;
+ optional int32 triggerMethod = 31;
+
+ // extended order fields
+ optional string activeStartTime = 32;
+ optional string activeStopTime = 33;
+
+ // advisor allocation orders
+ optional string faGroup = 34;
+ optional string faMethod = 35;
+ optional string faPercentage = 36;
+
+ // volatility orders
+ optional double volatility = 37;
+ optional int32 volatilityType = 38;
+ optional bool continuousUpdate = 39;
+ optional int32 referencePriceType = 40;
+ optional string deltaNeutralOrderType = 41;
+ optional double deltaNeutralAuxPrice = 42;
+ optional int32 deltaNeutralConId = 43;
+ optional string deltaNeutralOpenClose = 44;
+ optional bool deltaNeutralShortSale = 45;
+ optional int32 deltaNeutralShortSaleSlot = 46;
+ optional string deltaNeutralDesignatedLocation = 47;
+
+ // scale orders
+ optional int32 scaleInitLevelSize = 48;
+ optional int32 scaleSubsLevelSize = 49;
+ optional double scalePriceIncrement = 50;
+ optional double scalePriceAdjustValue = 51;
+ optional int32 scalePriceAdjustInterval = 52;
+ optional double scaleProfitOffset = 53;
+ optional bool scaleAutoReset = 54;
+ optional int32 scaleInitPosition = 55;
+ optional int32 scaleInitFillQty = 56;
+ optional bool scaleRandomPercent = 57;
+ optional string scaleTable = 58;
+
+ // hedge orders
+ optional string hedgeType = 59;
+ optional string hedgeParam = 60;
+
+ // algo orders
+ optional string algoStrategy = 61;
+ map algoParams = 62;
+ optional string algoId = 63;
+
+ // combo orders
+ map smartComboRoutingParams = 64;
+
+ // processing control
+ optional bool whatIf = 65;
+ optional bool transmit = 66;
+ optional bool overridePercentageConstraints = 67;
+
+ // Institutional orders only
+ optional string openClose = 68;
+ optional int32 origin = 69;
+ optional int32 shortSaleSlot = 70;
+ optional string designatedLocation = 71;
+ optional int32 exemptCode = 72;
+ optional string deltaNeutralSettlingFirm = 73;
+ optional string deltaNeutralClearingAccount = 74;
+ optional string deltaNeutralClearingIntent = 75;
+
+ // SMART routing only
+ optional double discretionaryAmt = 76;
+ optional bool optOutSmartRouting = 77;
+
+ // BOX ORDERS ONLY
+ optional double startingPrice = 78;
+ optional double stockRefPrice = 79;
+ optional double delta = 80;
+
+ // pegged to stock or VOL orders
+ optional double stockRangeLower = 81;
+ optional double stockRangeUpper = 82;
+
+ // Not Held
+ optional bool notHeld = 83;
+
+ // order misc options
+ map orderMiscOptions = 84;
+
+ //order algo id
+ optional bool solicited = 85;
+
+ optional bool randomizeSize = 86;
+ optional bool randomizePrice = 87;
+
+ // PEG2BENCH fields
+ optional int32 referenceContractId = 88;
+ optional double peggedChangeAmount = 89;
+ optional bool isPeggedChangeAmountDecrease = 90;
+ optional double referenceChangeAmount = 91;
+ optional string referenceExchangeId = 92;
+ optional string adjustedOrderType = 93;
+ optional double triggerPrice = 94;
+ optional double adjustedStopPrice = 95;
+ optional double adjustedStopLimitPrice = 96;
+ optional double adjustedTrailingAmount = 97;
+ optional int32 adjustableTrailingUnit = 98;
+ optional double lmtPriceOffset = 99;
+
+ repeated OrderCondition conditions = 100;
+ optional bool conditionsCancelOrder = 101;
+ optional bool conditionsIgnoreRth = 102;
+
+ // models
+ optional string modelCode = 103;
+
+ optional string extOperator = 104;
+
+ optional SoftDollarTier softDollarTier = 105;
+
+ // native cash quantity
+ optional double cashQty = 106;
+
+ optional string mifid2DecisionMaker = 107;
+ optional string mifid2DecisionAlgo = 108;
+ optional string mifid2ExecutionTrader = 109;
+ optional string mifid2ExecutionAlgo = 110;
+
+ // don't use auto price for hedge
+ optional bool dontUseAutoPriceForHedge = 111;
+
+ optional bool isOmsContainer = 112;
+ optional bool discretionaryUpToLimitPrice = 113;
+
+ optional string autoCancelDate = 114;
+ optional string filledQuantity = 115;
+ optional int32 refFuturesConId = 116;
+ optional bool autoCancelParent = 117;
+ optional string shareholder = 118;
+ optional bool imbalanceOnly = 119;
+ optional int32 routeMarketableToBbo = 120;
+ optional int64 parentPermId = 121;
+
+ optional int32 usePriceMgmtAlgo = 122;
+ optional int32 duration = 123;
+ optional int32 postToAts = 124;
+ optional string advancedErrorOverride = 125;
+ optional string manualOrderTime = 126;
+ optional int32 minTradeQty = 127;
+ optional int32 minCompeteSize = 128;
+ optional double competeAgainstBestOffset = 129;
+ optional double midOffsetAtWhole = 130;
+ optional double midOffsetAtHalf = 131;
+ optional string customerAccount = 132;
+ optional bool professionalCustomer = 133;
+ optional string bondAccruedInterest = 134;
+ optional bool includeOvernight = 135;
+ optional int32 manualOrderIndicator = 136;
+ optional string submitter = 137;
+ optional bool deactivate = 138;
+ optional bool postOnly = 139;
+ optional bool allowPreOpen = 140;
+ optional bool ignoreOpenAuction = 141;
+ optional int32 seekPriceImprovement = 142;
+ optional int32 whatIfType = 143;
+}
diff --git a/packages/ibkr/ref/source/proto/OrderAllocation.proto b/packages/ibkr/ref/source/proto/OrderAllocation.proto
new file mode 100644
index 00000000..f94b35ab
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrderAllocation.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OrderAllocationProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrderAllocation {
+ optional string account = 1;
+ optional string position = 2;
+ optional string positionDesired = 3;
+ optional string positionAfter = 4;
+ optional string desiredAllocQty = 5;
+ optional string allowedAllocQty = 6;
+ optional bool isMonetary = 7;
+}
diff --git a/packages/ibkr/ref/source/proto/OrderBound.proto b/packages/ibkr/ref/source/proto/OrderBound.proto
new file mode 100644
index 00000000..f5503865
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrderBound.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OrderBoundProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrderBound {
+ optional int64 permId = 1;
+ optional int32 clientId = 2;
+ optional int32 orderId = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/OrderCancel.proto b/packages/ibkr/ref/source/proto/OrderCancel.proto
new file mode 100644
index 00000000..2f1e13eb
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrderCancel.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OrderCancelProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrderCancel {
+ optional string manualOrderCancelTime = 1;
+ optional string extOperator = 2;
+ optional int32 manualOrderIndicator = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/OrderCondition.proto b/packages/ibkr/ref/source/proto/OrderCondition.proto
new file mode 100644
index 00000000..c15d19eb
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrderCondition.proto
@@ -0,0 +1,26 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OrderConditionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrderCondition {
+ optional int32 type = 1;
+ optional bool isConjunctionConnection = 2;
+ optional bool isMore = 3;
+ optional int32 conId = 4;
+ optional string exchange = 5;
+ optional string symbol = 6;
+ optional string secType = 7;
+ optional int32 percent = 8;
+ optional double changePercent = 9;
+ optional double price = 10;
+ optional int32 triggerMethod = 11;
+ optional string time = 12;
+ optional int32 volume = 13;
+}
diff --git a/packages/ibkr/ref/source/proto/OrderState.proto b/packages/ibkr/ref/source/proto/OrderState.proto
new file mode 100644
index 00000000..baaf9aa9
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrderState.proto
@@ -0,0 +1,48 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "OrderAllocation.proto";
+
+option java_outer_classname = "OrderStateProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrderState {
+ optional string status = 1;
+ optional double initMarginBefore = 2;
+ optional double maintMarginBefore = 3;
+ optional double equityWithLoanBefore = 4;
+ optional double initMarginChange = 5;
+ optional double maintMarginChange = 6;
+ optional double equityWithLoanChange = 7;
+ optional double initMarginAfter = 8;
+ optional double maintMarginAfter = 9;
+ optional double equityWithLoanAfter = 10;
+
+ optional double commissionAndFees = 11;
+ optional double minCommissionAndFees = 12;
+ optional double maxCommissionAndFees = 13;
+ optional string commissionAndFeesCurrency = 14;
+ optional string marginCurrency = 15;
+
+ optional double initMarginBeforeOutsideRTH = 16;
+ optional double maintMarginBeforeOutsideRTH = 17;
+ optional double equityWithLoanBeforeOutsideRTH = 18;
+ optional double initMarginChangeOutsideRTH = 19;
+ optional double maintMarginChangeOutsideRTH = 20;
+ optional double equityWithLoanChangeOutsideRTH = 21;
+ optional double initMarginAfterOutsideRTH = 22;
+ optional double maintMarginAfterOutsideRTH = 23;
+ optional double equityWithLoanAfterOutsideRTH = 24;
+
+ optional string suggestedSize = 25;
+ optional string rejectReason = 26;
+ repeated OrderAllocation orderAllocations = 27;
+ optional string warningText = 28;
+ optional string completedTime = 29;
+ optional string completedStatus = 30;
+}
diff --git a/packages/ibkr/ref/source/proto/OrderStatus.proto b/packages/ibkr/ref/source/proto/OrderStatus.proto
new file mode 100644
index 00000000..23d624a0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrderStatus.proto
@@ -0,0 +1,24 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OrderStatusProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrderStatus {
+ optional int32 orderId = 1;
+ optional string status = 2;
+ optional string filled = 3;
+ optional string remaining = 4;
+ optional double avgFillPrice = 5;
+ optional int64 permId = 6;
+ optional int32 parentId = 7;
+ optional double lastFillPrice = 8;
+ optional int32 clientId = 9;
+ optional string whyHeld = 10;
+ optional double mktCapPrice = 11;
+}
diff --git a/packages/ibkr/ref/source/proto/OrdersConfig.proto b/packages/ibkr/ref/source/proto/OrdersConfig.proto
new file mode 100644
index 00000000..fefb32d1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrdersConfig.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "OrdersSmartRoutingConfig.proto";
+
+option java_outer_classname = "OrdersConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrdersConfig {
+ OrdersSmartRoutingConfig smartRouting = 1;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/OrdersSmartRoutingConfig.proto b/packages/ibkr/ref/source/proto/OrdersSmartRoutingConfig.proto
new file mode 100644
index 00000000..361403d6
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/OrdersSmartRoutingConfig.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "OrdersSmartRoutingConfigProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message OrdersSmartRoutingConfig {
+ optional bool seekPriceImprovement = 1;
+ optional bool preOpenReroute = 2;
+ optional bool doNotRouteToDarkPools = 3;
+ optional string defaultAlgorithm = 4;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/PlaceOrderRequest.proto b/packages/ibkr/ref/source/proto/PlaceOrderRequest.proto
new file mode 100644
index 00000000..d75717ce
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PlaceOrderRequest.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+import "Order.proto";
+import "AttachedOrders.proto";
+
+option java_outer_classname = "PlaceOrderRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PlaceOrderRequest {
+ optional int32 orderId = 1;
+ optional Contract contract = 2;
+ optional Order order = 3;
+ optional AttachedOrders attachedOrders = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/PnL.proto b/packages/ibkr/ref/source/proto/PnL.proto
new file mode 100644
index 00000000..49a9a86a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PnL.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PnLProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PnL {
+ optional int32 reqId = 1;
+ optional double dailyPnL = 2;
+ optional double unrealizedPnL = 3;
+ optional double realizedPnL = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/PnLRequest.proto b/packages/ibkr/ref/source/proto/PnLRequest.proto
new file mode 100644
index 00000000..f2703b8b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PnLRequest.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PnLRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PnLRequest {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional string modelCode = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/PnLSingle.proto b/packages/ibkr/ref/source/proto/PnLSingle.proto
new file mode 100644
index 00000000..ca37a930
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PnLSingle.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PnLSingleProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PnLSingle {
+ optional int32 reqId = 1;
+ optional string position = 2;
+ optional double dailyPnL = 3;
+ optional double unrealizedPnL = 4;
+ optional double realizedPnL = 5;
+ optional double value = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/PnLSingleRequest.proto b/packages/ibkr/ref/source/proto/PnLSingleRequest.proto
new file mode 100644
index 00000000..2448d9c1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PnLSingleRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PnLSingleRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PnLSingleRequest {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional string modelCode = 3;
+ optional int32 conId = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/PortfolioValue.proto b/packages/ibkr/ref/source/proto/PortfolioValue.proto
new file mode 100644
index 00000000..2ae4450c
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PortfolioValue.proto
@@ -0,0 +1,23 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "PortfolioValueProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PortfolioValue {
+ optional Contract contract = 1;
+ optional string position = 2;
+ optional double marketPrice = 3;
+ optional double marketValue = 4;
+ optional double averageCost = 5;
+ optional double unrealizedPNL = 6;
+ optional double realizedPNL = 7;
+ optional string accountName = 8;
+}
diff --git a/packages/ibkr/ref/source/proto/Position.proto b/packages/ibkr/ref/source/proto/Position.proto
new file mode 100644
index 00000000..25d151ff
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/Position.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "PositionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message Position {
+ optional string account = 1;
+ optional Contract contract = 2;
+ optional string position = 3;
+ optional double avgCost = 4;
+}
diff --git a/packages/ibkr/ref/source/proto/PositionEnd.proto b/packages/ibkr/ref/source/proto/PositionEnd.proto
new file mode 100644
index 00000000..0c454443
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PositionEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PositionEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PositionEnd {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/PositionMulti.proto b/packages/ibkr/ref/source/proto/PositionMulti.proto
new file mode 100644
index 00000000..1f6b7faa
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PositionMulti.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "PositionMultiProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PositionMulti {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional Contract contract = 3;
+ optional string position = 4;
+ optional double avgCost = 5;
+ optional string modelCode = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/PositionMultiEnd.proto b/packages/ibkr/ref/source/proto/PositionMultiEnd.proto
new file mode 100644
index 00000000..681a22d0
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PositionMultiEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PositionMultiEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PositionMultiEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/PositionsMultiRequest.proto b/packages/ibkr/ref/source/proto/PositionsMultiRequest.proto
new file mode 100644
index 00000000..c2614711
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PositionsMultiRequest.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PositionsMultiRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PositionsMultiRequest {
+ optional int32 reqId = 1;
+ optional string account = 2;
+ optional string modelCode = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/PositionsRequest.proto b/packages/ibkr/ref/source/proto/PositionsRequest.proto
new file mode 100644
index 00000000..8103defb
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PositionsRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PositionsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PositionsRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/PriceIncrement.proto b/packages/ibkr/ref/source/proto/PriceIncrement.proto
new file mode 100644
index 00000000..9fd6a48d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/PriceIncrement.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "PriceIncrementProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message PriceIncrement {
+ optional double lowEdge = 1;
+ optional double increment = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/QueryDisplayGroupsRequest.proto b/packages/ibkr/ref/source/proto/QueryDisplayGroupsRequest.proto
new file mode 100644
index 00000000..5390d471
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/QueryDisplayGroupsRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "QueryDisplayGroupsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message QueryDisplayGroupsRequest {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/RealTimeBarTick.proto b/packages/ibkr/ref/source/proto/RealTimeBarTick.proto
new file mode 100644
index 00000000..bc7857ba
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/RealTimeBarTick.proto
@@ -0,0 +1,22 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "RealTimeBarTickProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message RealTimeBarTick {
+ optional int32 reqId = 1;
+ optional int64 time = 2;
+ optional double open = 3;
+ optional double high = 4;
+ optional double low = 5;
+ optional double close = 6;
+ optional string volume = 7;
+ optional string WAP = 8;
+ optional int32 count = 9;
+}
diff --git a/packages/ibkr/ref/source/proto/RealTimeBarsRequest.proto b/packages/ibkr/ref/source/proto/RealTimeBarsRequest.proto
new file mode 100644
index 00000000..f59ef2fd
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/RealTimeBarsRequest.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "RealTimeBarsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message RealTimeBarsRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional int32 barSize = 3;
+ optional string whatToShow = 4;
+ optional bool useRTH = 5;
+ map realTimeBarsOptions = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/ReceiveFA.proto b/packages/ibkr/ref/source/proto/ReceiveFA.proto
new file mode 100644
index 00000000..a50e5dc8
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ReceiveFA.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ReceiveFAProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ReceiveFA {
+ optional int32 faDataType = 1;
+ optional string xml = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/ReplaceFAEnd.proto b/packages/ibkr/ref/source/proto/ReplaceFAEnd.proto
new file mode 100644
index 00000000..b66782b8
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ReplaceFAEnd.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ReplaceFAEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ReplaceFAEnd {
+ optional int32 reqId = 1;
+ optional string text = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/RerouteMarketDataRequest.proto b/packages/ibkr/ref/source/proto/RerouteMarketDataRequest.proto
new file mode 100644
index 00000000..e9db7511
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/RerouteMarketDataRequest.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "RerouteMarketDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message RerouteMarketDataRequest {
+ optional int32 reqId = 1;
+ optional int32 conId = 2;
+ optional string exchange = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/RerouteMarketDepthRequest.proto b/packages/ibkr/ref/source/proto/RerouteMarketDepthRequest.proto
new file mode 100644
index 00000000..bfeb1469
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/RerouteMarketDepthRequest.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "RerouteMarketDepthRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message RerouteMarketDepthRequest {
+ optional int32 reqId = 1;
+ optional int32 conId = 2;
+ optional string exchange = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/ScannerData.proto b/packages/ibkr/ref/source/proto/ScannerData.proto
new file mode 100644
index 00000000..0ab77630
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ScannerData.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "ScannerDataElement.proto";
+
+option java_outer_classname = "ScannerDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ScannerData {
+ optional int32 reqId = 1;
+ repeated ScannerDataElement scannerDataElement = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/ScannerDataElement.proto b/packages/ibkr/ref/source/proto/ScannerDataElement.proto
new file mode 100644
index 00000000..e2a53b38
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ScannerDataElement.proto
@@ -0,0 +1,22 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "ScannerDataElementProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ScannerDataElement {
+ optional int32 rank = 1;
+ optional Contract contract = 2;
+ optional string marketName = 3;
+ optional string distance = 4;
+ optional string benchmark = 5;
+ optional string projection = 6;
+ optional string comboKey = 7;
+}
diff --git a/packages/ibkr/ref/source/proto/ScannerParameters.proto b/packages/ibkr/ref/source/proto/ScannerParameters.proto
new file mode 100644
index 00000000..617070cf
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ScannerParameters.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ScannerParametersProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ScannerParameters {
+ optional string xml = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/ScannerParametersRequest.proto b/packages/ibkr/ref/source/proto/ScannerParametersRequest.proto
new file mode 100644
index 00000000..a4d9bf97
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ScannerParametersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ScannerParametersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ScannerParametersRequest {
+ // empty
+}
diff --git a/packages/ibkr/ref/source/proto/ScannerSubscription.proto b/packages/ibkr/ref/source/proto/ScannerSubscription.proto
new file mode 100644
index 00000000..fecce6fa
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ScannerSubscription.proto
@@ -0,0 +1,36 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "ScannerSubscriptionProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ScannerSubscription {
+ optional int32 numberOfRows = 1;
+ optional string instrument = 2;
+ optional string locationCode = 3;
+ optional string scanCode = 4;
+ optional double abovePrice = 5;
+ optional double belowPrice = 6;
+ optional int64 aboveVolume = 7;
+ optional double marketCapAbove = 8;
+ optional double marketCapBelow = 9;
+ optional string moodyRatingAbove = 10;
+ optional string moodyRatingBelow = 11;
+ optional string spRatingAbove = 12;
+ optional string spRatingBelow = 13;
+ optional string maturityDateAbove = 14;
+ optional string maturityDateBelow = 15;
+ optional double couponRateAbove = 16;
+ optional double couponRateBelow = 17;
+ optional bool excludeConvertible = 18;
+ optional int64 averageOptionVolumeAbove = 19;
+ optional string scannerSettingPairs = 20;
+ optional string stockTypeFilter = 21;
+ map scannerSubscriptionFilterOptions = 22;
+ map scannerSubscriptionOptions = 23;
+}
diff --git a/packages/ibkr/ref/source/proto/ScannerSubscriptionRequest.proto b/packages/ibkr/ref/source/proto/ScannerSubscriptionRequest.proto
new file mode 100644
index 00000000..366feb76
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/ScannerSubscriptionRequest.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "ScannerSubscription.proto";
+
+option java_outer_classname = "ScannerSubscriptionRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message ScannerSubscriptionRequest {
+ optional int32 reqId = 1;
+ optional ScannerSubscription scannerSubscription = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/SecDefOptParameter.proto b/packages/ibkr/ref/source/proto/SecDefOptParameter.proto
new file mode 100644
index 00000000..446c2363
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SecDefOptParameter.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SecDefOptParameterProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SecDefOptParameter {
+ optional int32 reqId = 1;
+ optional string exchange = 2;
+ optional int32 underlyingConId = 3;
+ optional string tradingClass = 4;
+ optional string multiplier = 5;
+ repeated string expirations = 6;
+ repeated double strikes = 7;
+}
diff --git a/packages/ibkr/ref/source/proto/SecDefOptParameterEnd.proto b/packages/ibkr/ref/source/proto/SecDefOptParameterEnd.proto
new file mode 100644
index 00000000..75d0dc67
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SecDefOptParameterEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SecDefOptParameterEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SecDefOptParameterEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/SecDefOptParamsRequest.proto b/packages/ibkr/ref/source/proto/SecDefOptParamsRequest.proto
new file mode 100644
index 00000000..e6722065
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SecDefOptParamsRequest.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SecDefOptParamsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SecDefOptParamsRequest {
+ optional int32 reqId = 1;
+ optional string underlyingSymbol = 2;
+ optional string futFopExchange = 3;
+ optional string underlyingSecType = 4;
+ optional int32 underlyingConId = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/SetServerLogLevelRequest.proto b/packages/ibkr/ref/source/proto/SetServerLogLevelRequest.proto
new file mode 100644
index 00000000..cdcf528f
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SetServerLogLevelRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SetServerLogLevelRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SetServerLogLevelRequest {
+ optional int32 logLevel = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/SmartComponent.proto b/packages/ibkr/ref/source/proto/SmartComponent.proto
new file mode 100644
index 00000000..5febd550
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SmartComponent.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SmartComponentProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SmartComponent {
+ optional int32 bitNumber = 1;
+ optional string exchange = 2;
+ optional string exchangeLetter = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/SmartComponents.proto b/packages/ibkr/ref/source/proto/SmartComponents.proto
new file mode 100644
index 00000000..591bb4d9
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SmartComponents.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "SmartComponent.proto";
+
+option java_outer_classname = "SmartComponentsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SmartComponents {
+ optional int32 reqId = 1;
+ repeated SmartComponent smartComponents = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/SmartComponentsRequest.proto b/packages/ibkr/ref/source/proto/SmartComponentsRequest.proto
new file mode 100644
index 00000000..158c2113
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SmartComponentsRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SmartComponentsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SmartComponentsRequest {
+ optional int32 reqId = 1;
+ optional string bboExchange = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/SoftDollarTier.proto b/packages/ibkr/ref/source/proto/SoftDollarTier.proto
new file mode 100644
index 00000000..9571ecd7
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SoftDollarTier.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SoftDollarTierProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SoftDollarTier {
+ optional string name = 1;
+ optional string value = 2;
+ optional string displayName = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/SoftDollarTiers.proto b/packages/ibkr/ref/source/proto/SoftDollarTiers.proto
new file mode 100644
index 00000000..391d2625
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SoftDollarTiers.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "SoftDollarTier.proto";
+
+option java_outer_classname = "SoftDollarTiersProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SoftDollarTiers {
+ optional int32 reqId = 1;
+ repeated SoftDollarTier softDollarTiers = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/SoftDollarTiersRequest.proto b/packages/ibkr/ref/source/proto/SoftDollarTiersRequest.proto
new file mode 100644
index 00000000..1de50ae1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SoftDollarTiersRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SoftDollarTiersRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SoftDollarTiersRequest {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/StartApiRequest.proto b/packages/ibkr/ref/source/proto/StartApiRequest.proto
new file mode 100644
index 00000000..a22a2059
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/StartApiRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "StartApiRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message StartApiRequest {
+ optional int32 clientId = 1;
+ optional string optionalCapabilities = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/SubscribeToGroupEventsRequest.proto b/packages/ibkr/ref/source/proto/SubscribeToGroupEventsRequest.proto
new file mode 100644
index 00000000..754ea9b1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SubscribeToGroupEventsRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "SubscribeToGroupEventsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SubscribeToGroupEventsRequest {
+ optional int32 reqId = 1;
+ optional int32 groupId = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/SymbolSamples.proto b/packages/ibkr/ref/source/proto/SymbolSamples.proto
new file mode 100644
index 00000000..88520b6d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/SymbolSamples.proto
@@ -0,0 +1,17 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "ContractDescription.proto";
+
+option java_outer_classname = "SymbolSamplesProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message SymbolSamples {
+ optional int32 reqId = 1;
+ repeated ContractDescription contractDescriptions = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/TickAttribBidAsk.proto b/packages/ibkr/ref/source/proto/TickAttribBidAsk.proto
new file mode 100644
index 00000000..fc9a49cd
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickAttribBidAsk.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickAttribBidAskProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickAttribBidAsk {
+ optional bool bidPastLow = 1;
+ optional bool askPastHigh = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/TickAttribLast.proto b/packages/ibkr/ref/source/proto/TickAttribLast.proto
new file mode 100644
index 00000000..64ff5bf5
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickAttribLast.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickAttribLastProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickAttribLast {
+ optional bool pastLimit = 1;
+ optional bool unreported = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/TickByTickData.proto b/packages/ibkr/ref/source/proto/TickByTickData.proto
new file mode 100644
index 00000000..fb84e928
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickByTickData.proto
@@ -0,0 +1,24 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "HistoricalTickLast.proto";
+import "HistoricalTickBidAsk.proto";
+import "HistoricalTick.proto";
+
+option java_outer_classname = "TickByTickDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickByTickData {
+ optional int32 reqId = 1;
+ optional int32 tickType = 2;
+ oneof tick {
+ HistoricalTickLast historicalTickLast = 3;
+ HistoricalTickBidAsk historicalTickBidAsk = 4;
+ HistoricalTick historicalTickMidPoint = 5;
+ }
+}
diff --git a/packages/ibkr/ref/source/proto/TickByTickRequest.proto b/packages/ibkr/ref/source/proto/TickByTickRequest.proto
new file mode 100644
index 00000000..90ffde34
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickByTickRequest.proto
@@ -0,0 +1,20 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "Contract.proto";
+
+option java_outer_classname = "TickByTickRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickByTickRequest {
+ optional int32 reqId = 1;
+ optional Contract contract = 2;
+ optional string tickType = 3;
+ optional int32 numberOfTicks = 4;
+ optional bool ignoreSize = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/TickGeneric.proto b/packages/ibkr/ref/source/proto/TickGeneric.proto
new file mode 100644
index 00000000..ef33ab10
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickGeneric.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickGenericProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickGeneric {
+ optional int32 reqId = 1;
+ optional int32 tickType = 2;
+ optional double value = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/TickNews.proto b/packages/ibkr/ref/source/proto/TickNews.proto
new file mode 100644
index 00000000..c3332c5b
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickNews.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickNewsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickNews {
+ optional int32 reqId = 1;
+ optional int64 timestamp = 2;
+ optional string providerCode = 3;
+ optional string articleId = 4;
+ optional string headline = 5;
+ optional string extraData = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/TickOptionComputation.proto b/packages/ibkr/ref/source/proto/TickOptionComputation.proto
new file mode 100644
index 00000000..afdff8ac
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickOptionComputation.proto
@@ -0,0 +1,24 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickOptionComputationProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickOptionComputation {
+ optional int32 reqId = 1;
+ optional int32 tickType = 2;
+ optional int32 tickAttrib = 3;
+ optional double impliedVol = 4;
+ optional double delta = 5;
+ optional double optPrice = 6;
+ optional double pvDividend = 7;
+ optional double gamma = 8;
+ optional double vega = 9;
+ optional double theta = 10;
+ optional double undPrice = 11;
+}
diff --git a/packages/ibkr/ref/source/proto/TickPrice.proto b/packages/ibkr/ref/source/proto/TickPrice.proto
new file mode 100644
index 00000000..8988f48d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickPrice.proto
@@ -0,0 +1,18 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickPriceProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickPrice {
+ optional int32 reqId = 1;
+ optional int32 tickType = 2;
+ optional double price = 3;
+ optional string size = 4;
+ optional int32 attrMask = 5;
+}
diff --git a/packages/ibkr/ref/source/proto/TickReqParams.proto b/packages/ibkr/ref/source/proto/TickReqParams.proto
new file mode 100644
index 00000000..be6ecae5
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickReqParams.proto
@@ -0,0 +1,19 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickReqParamsProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickReqParams {
+ optional int32 reqId = 1;
+ optional string minTick = 2;
+ optional string bboExchange = 3;
+ optional int32 snapshotPermissions = 4;
+ optional string lastPricePrecision = 5;
+ optional string lastSizePrecision = 6;
+}
diff --git a/packages/ibkr/ref/source/proto/TickSize.proto b/packages/ibkr/ref/source/proto/TickSize.proto
new file mode 100644
index 00000000..e6aed7d6
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickSize.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickSizeProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickSize {
+ optional int32 reqId = 1;
+ optional int32 tickType = 2;
+ optional string size = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/TickSnapshotEnd.proto b/packages/ibkr/ref/source/proto/TickSnapshotEnd.proto
new file mode 100644
index 00000000..ca1e3b87
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickSnapshotEnd.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickSnapshotEndProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickSnapshotEnd {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/TickString.proto b/packages/ibkr/ref/source/proto/TickString.proto
new file mode 100644
index 00000000..91d2022d
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/TickString.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "TickStringProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message TickString {
+ optional int32 reqId = 1;
+ optional int32 tickType = 2;
+ optional string value = 3;
+}
diff --git a/packages/ibkr/ref/source/proto/UnsubscribeFromGroupEventsRequest.proto b/packages/ibkr/ref/source/proto/UnsubscribeFromGroupEventsRequest.proto
new file mode 100644
index 00000000..20d7fd4e
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UnsubscribeFromGroupEventsRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "UnsubscribeFromGroupEventsRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UnsubscribeFromGroupEventsRequest {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/UpdateConfigRequest.proto b/packages/ibkr/ref/source/proto/UpdateConfigRequest.proto
new file mode 100644
index 00000000..59d56f94
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UpdateConfigRequest.proto
@@ -0,0 +1,26 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "LockAndExitConfig.proto";
+import "MessageConfig.proto";
+import "ApiConfig.proto";
+import "OrdersConfig.proto";
+import "UpdateConfigWarning.proto";
+
+option java_outer_classname = "UpdateConfigRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UpdateConfigRequest {
+ optional int32 reqId = 1;
+ optional LockAndExitConfig lockAndExit = 2;
+ repeated MessageConfig messages = 3;
+ optional ApiConfig api = 4;
+ optional OrdersConfig orders = 5;
+ repeated UpdateConfigWarning acceptedWarnings = 6;
+ optional bool resetAPIOrderSequence = 7;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/UpdateConfigResponse.proto b/packages/ibkr/ref/source/proto/UpdateConfigResponse.proto
new file mode 100644
index 00000000..4d87a844
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UpdateConfigResponse.proto
@@ -0,0 +1,21 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+import "UpdateConfigWarning.proto";
+
+option java_outer_classname = "UpdateConfigResponseProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UpdateConfigResponse {
+ optional int32 reqId = 1;
+ optional string status = 2;
+ optional string message = 3;
+ repeated string changedFields = 4;
+ repeated string errors = 5;
+ repeated UpdateConfigWarning warnings = 6;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/UpdateConfigWarning.proto b/packages/ibkr/ref/source/proto/UpdateConfigWarning.proto
new file mode 100644
index 00000000..94910de4
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UpdateConfigWarning.proto
@@ -0,0 +1,16 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "UpdateConfigWarningProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UpdateConfigWarning {
+ optional int32 messageId = 1;
+ optional string title = 2;
+ optional string message = 3;
+}
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/proto/UpdateDisplayGroupRequest.proto b/packages/ibkr/ref/source/proto/UpdateDisplayGroupRequest.proto
new file mode 100644
index 00000000..d5f895b4
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UpdateDisplayGroupRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "UpdateDisplayGroupRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UpdateDisplayGroupRequest {
+ optional int32 reqId = 1;
+ optional string contractInfo = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/UserInfo.proto b/packages/ibkr/ref/source/proto/UserInfo.proto
new file mode 100644
index 00000000..39cad51a
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UserInfo.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "UserInfoProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UserInfo {
+ optional int32 reqId = 1;
+ optional string whiteBrandingId = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/UserInfoRequest.proto b/packages/ibkr/ref/source/proto/UserInfoRequest.proto
new file mode 100644
index 00000000..98300117
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/UserInfoRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "UserInfoRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message UserInfoRequest {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/VerifyCompleted.proto b/packages/ibkr/ref/source/proto/VerifyCompleted.proto
new file mode 100644
index 00000000..b6190979
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/VerifyCompleted.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "VerifyCompletedProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message VerifyCompleted {
+ optional bool isSuccessful = 1;
+ optional string errorText = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/VerifyMessageApi.proto b/packages/ibkr/ref/source/proto/VerifyMessageApi.proto
new file mode 100644
index 00000000..973457de
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/VerifyMessageApi.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "VerifyMessageApiProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message VerifyMessageApi {
+ optional string apiData = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/VerifyMessageRequest.proto b/packages/ibkr/ref/source/proto/VerifyMessageRequest.proto
new file mode 100644
index 00000000..285a931e
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/VerifyMessageRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "VerifyMessageRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message VerifyMessageRequest {
+ optional string apiData = 1;
+}
diff --git a/packages/ibkr/ref/source/proto/VerifyRequest.proto b/packages/ibkr/ref/source/proto/VerifyRequest.proto
new file mode 100644
index 00000000..646e3d61
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/VerifyRequest.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "VerifyRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message VerifyRequest {
+ optional string apiName = 1;
+ optional string apiVersion = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/WshEventData.proto b/packages/ibkr/ref/source/proto/WshEventData.proto
new file mode 100644
index 00000000..c16b0caf
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/WshEventData.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "WshEventDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message WshEventData {
+ optional int32 reqId = 1;
+ optional string dataJson = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/WshEventDataRequest.proto b/packages/ibkr/ref/source/proto/WshEventDataRequest.proto
new file mode 100644
index 00000000..0c61c0b7
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/WshEventDataRequest.proto
@@ -0,0 +1,22 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "WshEventDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message WshEventDataRequest {
+ optional int32 reqId = 1;
+ optional int32 conId = 2;
+ optional string filter = 3;
+ optional bool fillWatchlist = 4;
+ optional bool fillPortfolio = 5;
+ optional bool fillCompetitors = 6;
+ optional string startDate = 7;
+ optional string endDate = 8;
+ optional int32 totalLimit = 9;
+}
diff --git a/packages/ibkr/ref/source/proto/WshMetaData.proto b/packages/ibkr/ref/source/proto/WshMetaData.proto
new file mode 100644
index 00000000..710f4078
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/WshMetaData.proto
@@ -0,0 +1,15 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "WshMetaDataProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message WshMetaData {
+ optional int32 reqId = 1;
+ optional string dataJson = 2;
+}
diff --git a/packages/ibkr/ref/source/proto/WshMetaDataRequest.proto b/packages/ibkr/ref/source/proto/WshMetaDataRequest.proto
new file mode 100644
index 00000000..34672ed1
--- /dev/null
+++ b/packages/ibkr/ref/source/proto/WshMetaDataRequest.proto
@@ -0,0 +1,14 @@
+/* Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */
+
+syntax = "proto3";
+
+package protobuf;
+
+option java_outer_classname = "WshMetaDataRequestProto";
+option java_package = "com.ib.client.protobuf";
+option csharp_namespace = "IBApi.protobuf";
+
+message WshMetaDataRequest {
+ optional int32 reqId = 1;
+}
diff --git a/packages/ibkr/ref/source/pythonclient/.gitignore b/packages/ibkr/ref/source/pythonclient/.gitignore
new file mode 100644
index 00000000..365f1301
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/.gitignore
@@ -0,0 +1,14 @@
+*.pyc
+tags
+__pycache__/*
+log/*
+*.log
+log.*
+core
+*.xml
+MANIFEST
+dist
+build
+.idea
+*.egg-info
+/.tox/
diff --git a/packages/ibkr/ref/source/pythonclient/MANIFEST.in b/packages/ibkr/ref/source/pythonclient/MANIFEST.in
new file mode 100644
index 00000000..5e2b6a5f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/MANIFEST.in
@@ -0,0 +1,2 @@
+include ibapi/*.py
+include README.md
diff --git a/packages/ibkr/ref/source/pythonclient/README.md b/packages/ibkr/ref/source/pythonclient/README.md
new file mode 100644
index 00000000..443dd74d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/README.md
@@ -0,0 +1,173 @@
+**Installation Guide for TWS API Library**
+
+This guide provides step-by-step instructions for setting up the TWS API library, including creating virtual environments using both Anaconda and standard Python, building distributions, and testing the installation.
+
+*Please see Understanding Code Organization and Functionality section at the bottom for an explanation of the key terms, conventions, and code organization used.*
+
+Step 1: Clone the TWS API repository and set up a virtual environment:
+
+- Open a terminal or Anaconda prompt on your Windows laptop.
+- Change to the directory where you want to store the TWS API repository.
+- Clone the TWS API repository from GitHub using git:
+
+```bash
+git clone https://github.com/your_username/tws-api.git
+```
+
+Replace `your_username` with your actual GitHub username.
+
+Step 2: Create a new Python virtual environment (using Anaconda):
+
+- First, ensure you are within the '\tws-api\source\pythonclient' folder inside the "tws-api" repository:
+
+```Anaconda Prompt
+cd tws-api/source/pythonclient
+```
+
+- Create a new Python virtual environment using Anaconda:
+
+```Anaconda Prompt
+conda create -n tws_env python=3.9
+```
+
+Replace `tws_env` with your desired environment name. Here, we are using Python 3.9 as an example, but you can choose another Python version if needed.
+
+- *Alternative: Create a new Python virtual environment without Anaconda:*
+
+```bash
+python3 -m venv tws_env
+```
+
+Replace `tws_env` with your desired environment name.
+
+Step 3: Activate the virtual environment:
+
+- Activate the newly created virtual environment:
+
+```Anaconda Prompt
+conda activate tws_env
+```
+
+- *Alternative: Activate the virtual environment without Anaconda:*
+
+```bash
+source tws_env/bin/activate
+```
+
+Step 4: Install the TWS API library:
+
+- Build the source distribution:
+
+```Anaconda Prompt
+python setup.py sdist
+```
+
+- Build the wheel distribution:
+
+```Anaconda Prompt
+python setup.py bdist_wheel
+```
+
+- Retrieve the wheel distribution file name from the dist folder under the tws-api/source/pythonclient folder:
+
+ For instance, if the wheel distribution file name is `ibapi-9.76.1-py3-none-any.whl`
+
+- Install the wheel distribution using `pip` with the `--user` flag using the following command:
+
+```Anaconda Prompt
+python3 -m pip install --user --upgrade dist/ibapi-9.76.1-py3-none-any.whl
+```
+
+Step 5: Create a new Jupyter kernel with the virtual environment:
+
+- Install Jupyter if you haven't already (skip this step if you have Jupyter installed):
+
+```Anaconda Prompt
+conda install jupyter
+```
+
+- Install the ipykernel package to enable creating a Jupyter kernel for the virtual environment:
+
+```Anaconda Prompt
+conda install ipykernel
+```
+
+- Create a new Jupyter kernel for the virtual environment:
+
+```Anaconda Prompt
+python -m ipykernel install --user --name tws_env --display-name "TWS Environment"
+```
+
+Replace `tws_env` with the same environment name used in Step 2.
+
+Step 6: Open Jupyter Notebook and select the new kernel:
+
+- Launch Jupyter Notebook:
+
+```Anaconda Prompt
+jupyter notebook
+```
+
+Step 7: Create a new Jupyter Notebook and test the TWS API library installed:
+
+- In the Jupyter Notebook interface, create a new notebook by clicking on "New" and then selecting "TWS Environment" from the list of available kernels.
+
+- Run the following code in the first cell of the notebook to test the TWS API library:
+```
+import ibapi
+
+print("TWS API version:", ibapi.__version__)
+```
+Congratulations, now you have a new Jupyter Notebook with the TWS API library installed in the virtual environment, and you can start coding and testing your trading strategies using the TWS API.
+
+
+
+**Understanding Code Organization and Functionality**
+
+This section provides insights into how the TWS API library is structured, how messages are received and sent, and how to interact with the Wrapper class for handling incoming messages. Understanding these concepts will help you effectively utilize the TWS API for your trading automation needs.
+
+A couple of things/definitions/conventions:
+* a *low level message* is some data prefixed with its size
+* a *high level message* is a list of fields separated by the NULL character; the fields are all strings; the message ID is the first field, the come others whose number and semantics depend on the message itself
+* a *request* is a message from client to TWS/IBGW (IB Gateway)
+* an *answer* is a message from TWS/IBGW to client
+
+
+How the code is organized:
+* *comm* module: has tools that know how to handle (eg: encode/decode) low and high level messages
+* *Connection*: glorified socket
+* *Reader*: thread that uses Connection to read packets, transform to low level messages and put in a Queue
+* *Decoder*: knows how to take a low level message and decode into high level message
+* *Client*:
+ + knows to send requests
+ + has the message loop which takes low level messages from Queue and uses Decoder to transform into high level message with which it then calls the corresponding Wrapper method
+* *Wrapper*: class that needs to be subclassed by the user so that it can get the incoming messages
+
+
+The info/data flow is:
+
+* receiving:
+ + *Connection.recv_msg()* (which is essentially a socket) receives the packets
+ - uses *Connection._recv_all_msgs()* which tries to combine smaller packets into bigger ones based on some trivial heuristic
+ + *Reader.run()* uses *Connection.recv_msg()* to get a packet and then uses *comm.read_msg()* to try to make it a low level message. If that can't be done yet (size prefix says so) then it waits for more packets
+ + if a full low level message is received then it is placed in the Queue (remember this is a standalone thread)
+ + the main thread runs the *Client.run()* loop which:
+ - gets a low level message from Queue
+ - uses *comm.py* to translate into high level message (fields)
+ - uses *Decoder.interpret()* to act based on that message
+ + *Decoder.interpret()* will translate the fields into function parameters of the correct type and call with the correct/corresponding method of *Wrapper* class
+
+* sending:
+ + *Client* class has methods that implement the _requests_. The user will call those request methods with the needed parameters and *Client* will send them to the TWS/IBGW.
+
+
+Implementation notes:
+
+* the *Decoder* has two ways of handling a message (essentially decoding the fields)
+ + some message very neatly map to a function call; meaning that the number of fields and order are the same as the method parameters. For example: Wrapper.tickSize(). In this case a simple mapping is made between the incoming msg id and the Wrapper method:
+
+ IN.TICK_SIZE: HandleInfo(wrap=Wrapper.tickSize),
+
+ + other messages are more complex, depend on version number heavily or need field massaging. In this case the incoming message id is mapped to a processing function that will do all that and call the Wrapper method at the end. For example:
+
+ IN.TICK_PRICE: HandleInfo(proc=processTickPriceMsg),
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/__init__.py b/packages/ibkr/ref/source/pythonclient/ibapi/__init__.py
new file mode 100644
index 00000000..61ba7896
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/__init__.py
@@ -0,0 +1,16 @@
+"""
+Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+""" Package implementing the Python API for the TWS/IB Gateway """
+
+VERSION = {"major": 10, "minor": 44, "micro": 1}
+
+
+def get_version_string():
+ version = "{major}.{minor}.{micro}".format(**VERSION)
+ return version
+
+
+__version__ = get_version_string()
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/account_summary_tags.py b/packages/ibkr/ref/source/pythonclient/ibapi/account_summary_tags.py
new file mode 100644
index 00000000..e8ae464b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/account_summary_tags.py
@@ -0,0 +1,70 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+class AccountSummaryTags:
+ AccountType = "AccountType"
+ NetLiquidation = "NetLiquidation"
+ TotalCashValue = "TotalCashValue"
+ SettledCash = "SettledCash"
+ AccruedCash = "AccruedCash"
+ BuyingPower = "BuyingPower"
+ EquityWithLoanValue = "EquityWithLoanValue"
+ PreviousDayEquityWithLoanValue = "PreviousDayEquityWithLoanValue"
+ GrossPositionValue = "GrossPositionValue"
+ ReqTEquity = "ReqTEquity"
+ ReqTMargin = "ReqTMargin"
+ SMA = "SMA"
+ InitMarginReq = "InitMarginReq"
+ MaintMarginReq = "MaintMarginReq"
+ AvailableFunds = "AvailableFunds"
+ ExcessLiquidity = "ExcessLiquidity"
+ Cushion = "Cushion"
+ FullInitMarginReq = "FullInitMarginReq"
+ FullMaintMarginReq = "FullMaintMarginReq"
+ FullAvailableFunds = "FullAvailableFunds"
+ FullExcessLiquidity = "FullExcessLiquidity"
+ LookAheadNextChange = "LookAheadNextChange"
+ LookAheadInitMarginReq = "LookAheadInitMarginReq"
+ LookAheadMaintMarginReq = "LookAheadMaintMarginReq"
+ LookAheadAvailableFunds = "LookAheadAvailableFunds"
+ LookAheadExcessLiquidity = "LookAheadExcessLiquidity"
+ HighestSeverity = "HighestSeverity"
+ DayTradesRemaining = "DayTradesRemaining"
+ Leverage = "Leverage"
+
+ AllTags = ",".join(
+ (
+ AccountType,
+ NetLiquidation,
+ TotalCashValue,
+ SettledCash,
+ AccruedCash,
+ BuyingPower,
+ EquityWithLoanValue,
+ PreviousDayEquityWithLoanValue,
+ GrossPositionValue,
+ ReqTEquity,
+ ReqTMargin,
+ SMA,
+ InitMarginReq,
+ MaintMarginReq,
+ AvailableFunds,
+ ExcessLiquidity,
+ Cushion,
+ FullInitMarginReq,
+ FullMaintMarginReq,
+ FullAvailableFunds,
+ FullExcessLiquidity,
+ LookAheadNextChange,
+ LookAheadInitMarginReq,
+ LookAheadMaintMarginReq,
+ LookAheadAvailableFunds,
+ LookAheadExcessLiquidity,
+ HighestSeverity,
+ DayTradesRemaining,
+ Leverage,
+ )
+ )
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/client.py b/packages/ibkr/ref/source/pythonclient/ibapi/client.py
new file mode 100644
index 00000000..de62d476
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/client.py
@@ -0,0 +1,7502 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+
+The main class to use from API user's point of view.
+It takes care of almost everything:
+- implementing the requests
+- creating the answer decoder
+- creating the connection to TWS/IBGW
+The user just needs to override EWrapper methods to receive the answers.
+"""
+
+import logging
+import queue
+import socket
+import sys
+
+from ibapi import decoder, reader, comm
+from ibapi.comm import make_field, make_field_handle_empty
+from ibapi.common import * # @UnusedWildImport
+from ibapi.connection import Connection
+from ibapi.const import NO_VALID_ID, MAX_MSG_LEN, UNSET_DOUBLE
+from ibapi.contract import Contract
+from ibapi.errors import (
+ NOT_CONNECTED,
+ CONNECT_FAIL,
+ BAD_LENGTH,
+ UPDATE_TWS,
+ FA_PROFILE_NOT_SUPPORTED,
+ ALREADY_CONNECTED, FAIL_SEND_REQMKT, FAIL_SEND_CANMKT,
+ FAIL_SEND_ACCT, FAIL_SEND_EXEC, FAIL_SEND_ORDER,
+ FAIL_SEND_CORDER, FAIL_SEND_OORDER, FAIL_SEND_REQCONTRACT, FAIL_SEND_REQMKTDEPTH, FAIL_SEND_CANMKTDEPTH,
+ FAIL_SEND_SERVER_LOG_LEVEL, FAIL_SEND_FA_REQUEST, FAIL_SEND_FA_REPLACE, FAIL_SEND_REQSCANNER, FAIL_SEND_CANSCANNER,
+ FAIL_SEND_REQSCANNERPARAMETERS, FAIL_SEND_REQHISTDATA, FAIL_SEND_CANHISTDATA, FAIL_SEND_REQRTBARS,
+ FAIL_SEND_CANRTBARS, FAIL_SEND_REQCURRTIME, FAIL_SEND_REQFUNDDATA, FAIL_SEND_CANFUNDDATA,
+ FAIL_SEND_REQCALCIMPLIEDVOLAT, FAIL_SEND_REQCALCOPTIONPRICE, FAIL_SEND_CANCALCIMPLIEDVOLAT,
+ FAIL_SEND_CANCALCOPTIONPRICE, FAIL_SEND_REQGLOBALCANCEL, FAIL_SEND_REQMARKETDATATYPE, FAIL_SEND_REQPOSITIONS,
+ FAIL_SEND_CANPOSITIONS, FAIL_SEND_REQACCOUNTDATA, FAIL_SEND_CANACCOUNTDATA, FAIL_SEND_VERIFYREQUEST,
+ FAIL_SEND_VERIFYMESSAGE, FAIL_SEND_QUERYDISPLAYGROUPS, FAIL_SEND_SUBSCRIBETOGROUPEVENTS,
+ FAIL_SEND_UPDATEDISPLAYGROUP, FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS, FAIL_SEND_STARTAPI,
+ FAIL_SEND_VERIFYANDAUTHREQUEST, FAIL_SEND_VERIFYANDAUTHMESSAGE, FAIL_SEND_REQPOSITIONSMULTI,
+ FAIL_SEND_CANPOSITIONSMULTI, FAIL_SEND_REQACCOUNTUPDATESMULTI, FAIL_SEND_CANACCOUNTUPDATESMULTI,
+ FAIL_SEND_REQSECDEFOPTPARAMS, FAIL_SEND_REQSOFTDOLLARTIERS, FAIL_SEND_REQFAMILYCODES, FAIL_SEND_REQMATCHINGSYMBOLS,
+ FAIL_SEND_REQMKTDEPTHEXCHANGES, FAIL_SEND_REQSMARTCOMPONENTS, FAIL_SEND_REQNEWSPROVIDERS, FAIL_SEND_REQNEWSARTICLE,
+ FAIL_SEND_REQHISTORICALNEWS, FAIL_SEND_REQHEADTIMESTAMP, FAIL_SEND_REQHISTOGRAMDATA, FAIL_SEND_CANCELHISTOGRAMDATA,
+ FAIL_SEND_CANCELHEADTIMESTAMP, FAIL_SEND_REQMARKETRULE, FAIL_SEND_REQPNL,
+ FAIL_SEND_CANCELPNL, FAIL_SEND_REQPNLSINGLE, FAIL_SEND_CANCELPNLSINGLE,
+ FAIL_SEND_REQHISTORICALTICKS, FAIL_SEND_REQTICKBYTICKDATA, FAIL_SEND_CANCELTICKBYTICKDATA,
+ FAIL_SEND_REQCOMPLETEDORDERS, FAIL_SEND_REQ_WSH_META_DATA, FAIL_SEND_CAN_WSH_META_DATA,
+ FAIL_SEND_REQ_WSH_EVENT_DATA, FAIL_SEND_CAN_WSH_EVENT_DATA, FAIL_SEND_REQ_USER_INFO,
+ FAIL_SEND_REQCURRTIMEINMILLIS, FAIL_SEND_CANCEL_CONTRACT_DATA, FAIL_SEND_CANCEL_HISTORICAL_TICKS,
+ FAIL_SEND_REQCONFIG, FAIL_SEND_UPDATECONFIG
+)
+from ibapi.execution import ExecutionFilter
+from ibapi.message import OUT
+from ibapi.order import Order, COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID
+from ibapi.order_cancel import OrderCancel
+from ibapi.scanner import ScannerSubscription
+from ibapi.server_versions import (
+ MIN_SERVER_VER_OPTIONAL_CAPABILITIES,
+ MIN_CLIENT_VER,
+ MAX_CLIENT_VER,
+ MIN_SERVER_VER_DELTA_NEUTRAL,
+ MIN_SERVER_VER_REQ_MKT_DATA_CONID,
+ MIN_SERVER_VER_TRADING_CLASS,
+ MIN_SERVER_VER_REQ_SMART_COMPONENTS,
+ MIN_SERVER_VER_LINKING,
+ MIN_SERVER_VER_REQ_MARKET_DATA_TYPE,
+ MIN_SERVER_VER_MARKET_RULES,
+ MIN_SERVER_VER_TICK_BY_TICK,
+ MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE,
+ MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT,
+ MIN_SERVER_VER_SCALE_ORDERS2,
+ MIN_SERVER_VER_ALGO_ORDERS,
+ MIN_SERVER_VER_NOT_HELD,
+ MIN_SERVER_VER_SEC_ID_TYPE,
+ MIN_SERVER_VER_PLACE_ORDER_CONID,
+ MIN_SERVER_VER_SSHORTX,
+ MIN_SERVER_VER_HEDGE_ORDERS,
+ MIN_SERVER_VER_OPT_OUT_SMART_ROUTING,
+ MIN_SERVER_VER_DELTA_NEUTRAL_CONID,
+ MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE,
+ MIN_SERVER_VER_SCALE_ORDERS3,
+ MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE,
+ MIN_SERVER_VER_TRAILING_PERCENT,
+ MIN_SERVER_VER_SCALE_TABLE,
+ MIN_SERVER_VER_ALGO_ID,
+ MIN_SERVER_VER_ORDER_SOLICITED,
+ MIN_SERVER_VER_MODELS_SUPPORT,
+ MIN_SERVER_VER_EXT_OPERATOR,
+ MIN_SERVER_VER_SOFT_DOLLAR_TIER,
+ MIN_SERVER_VER_CASH_QTY,
+ MIN_SERVER_VER_DECISION_MAKER,
+ MIN_SERVER_VER_MIFID_EXECUTION,
+ MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE,
+ MIN_SERVER_VER_ORDER_CONTAINER,
+ MIN_SERVER_VER_PRICE_MGMT_ALGO,
+ MIN_SERVER_VER_DURATION,
+ MIN_SERVER_VER_POST_TO_ATS,
+ MIN_SERVER_VER_AUTO_CANCEL_PARENT,
+ MIN_SERVER_VER_ADVANCED_ORDER_REJECT,
+ MIN_SERVER_VER_MANUAL_ORDER_TIME,
+ MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS,
+ MIN_SERVER_VER_FRACTIONAL_POSITIONS,
+ MIN_SERVER_VER_SSHORTX_OLD,
+ MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS,
+ MIN_SERVER_VER_FA_PROFILE_DESUPPORT,
+ MIN_SERVER_VER_PTA_ORDERS,
+ MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE,
+ MIN_SERVER_VER_PEGGED_TO_BENCHMARK,
+ MIN_SERVER_VER_D_PEG_ORDERS,
+ MIN_SERVER_VER_POSITIONS,
+ MIN_SERVER_VER_PNL,
+ MIN_SERVER_VER_EXECUTION_DATA_CHAIN,
+ MIN_SERVER_VER_BOND_ISSUERID,
+ MIN_SERVER_VER_CONTRACT_DATA_CHAIN,
+ MIN_SERVER_VER_PRIMARYEXCH,
+ MIN_SERVER_VER_REQ_MKT_DEPTH_EXCHANGES,
+ MIN_SERVER_VER_SMART_DEPTH,
+ MIN_SERVER_VER_MKT_DEPTH_PRIM_EXCHANGE,
+ MIN_SERVER_VER_REPLACE_FA_END,
+ MIN_SERVER_VER_HISTORICAL_SCHEDULE,
+ MIN_SERVER_VER_SYNT_REALTIME_BARS,
+ MIN_SERVER_VER_REQ_HEAD_TIMESTAMP,
+ MIN_SERVER_VER_CANCEL_HEADTIMESTAMP,
+ MIN_SERVER_VER_REQ_HISTOGRAM,
+ MIN_SERVER_VER_HISTORICAL_TICKS,
+ MIN_SERVER_VER_SCANNER_GENERIC_OPTS,
+ MIN_SERVER_VER_FUNDAMENTAL_DATA,
+ MIN_SERVER_VER_REQ_NEWS_PROVIDERS,
+ MIN_SERVER_VER_REQ_NEWS_ARTICLE,
+ MIN_SERVER_VER_NEWS_QUERY_ORIGINS,
+ MIN_SERVER_VER_REQ_HISTORICAL_NEWS,
+ MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ,
+ MIN_SERVER_VER_REQ_FAMILY_CODES,
+ MIN_SERVER_VER_REQ_MATCHING_SYMBOLS,
+ MIN_SERVER_VER_WSHE_CALENDAR,
+ MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS,
+ MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE,
+ MIN_SERVER_VER_USER_INFO,
+ MIN_SERVER_VER_MANUAL_ORDER_TIME_EXERCISE_OPTIONS,
+ MIN_SERVER_VER_CUSTOMER_ACCOUNT,
+ MIN_SERVER_VER_PROFESSIONAL_CUSTOMER,
+ MIN_SERVER_VER_RFQ_FIELDS,
+ MIN_SERVER_VER_INCLUDE_OVERNIGHT,
+ MIN_SERVER_VER_UNDO_RFQ_FIELDS,
+ MIN_SERVER_VER_CME_TAGGING_FIELDS,
+ MIN_SERVER_VER_CURRENT_TIME_IN_MILLIS,
+ MIN_SERVER_VER_IMBALANCE_ONLY,
+ MIN_SERVER_VER_PARAMETRIZED_DAYS_OF_EXECUTIONS,
+ MIN_SERVER_VER_PROTOBUF,
+ MIN_SERVER_VER_CANCEL_CONTRACT_DATA,
+ MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_1,
+ MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_2,
+ MIN_SERVER_VER_ATTACHED_ORDERS,
+ MIN_SERVER_VER_CONFIG,
+ MIN_SERVER_VER_UPDATE_CONFIG
+)
+
+from ibapi.utils import ClientException, log_
+from ibapi.utils import (
+ current_fn_name,
+ BadMessage,
+ isPegBenchOrder,
+ isPegMidOrder,
+ isPegBestOrder,
+ currentTimeMillis,
+)
+from ibapi.errors import INVALID_SYMBOL
+from ibapi.utils import isAsciiPrintable
+from ibapi.common import PROTOBUF_MSG_ID
+from ibapi.client_utils import createExecutionRequestProto, createPlaceOrderRequestProto, createCancelOrderRequestProto, createGlobalCancelRequestProto
+from ibapi.client_utils import createAllOpenOrdersRequestProto, createAutoOpenOrdersRequestProto, createOpenOrdersRequestProto, createCompletedOrdersRequestProto
+from ibapi.client_utils import createContractDataRequestProto, createMarketDataTypeRequestProto
+from ibapi.client_utils import createMarketDataRequestProto, createMarketDepthRequestProto, createCancelMarketDataProto, createCancelMarketDepthProto
+from ibapi.client_utils import createAccountSummaryRequestProto, createCancelAccountSummaryRequestProto, createManagedAccountsRequestProto
+from ibapi.client_utils import createAccountDataRequestProto, createPositionsRequestProto, createCancelPositionsRequestProto
+from ibapi.client_utils import createPositionsMultiRequestProto, createCancelPositionsMultiRequestProto, createAccountUpdatesMultiRequestProto, createCancelAccountUpdatesMultiRequestProto
+from ibapi.client_utils import createHistoricalDataRequestProto, createCancelHistoricalDataProto, createRealTimeBarsRequestProto, createCancelRealTimeBarsProto
+from ibapi.client_utils import createHeadTimestampRequestProto, createCancelHeadTimestampProto, createHistogramDataRequestProto, createCancelHistogramDataProto
+from ibapi.client_utils import createHistoricalTicksRequestProto, createTickByTickRequestProto, createCancelTickByTickProto
+from ibapi.client_utils import createNewsBulletinsRequestProto, createCancelNewsBulletinsProto, createNewsArticleRequestProto, createNewsProvidersRequestProto
+from ibapi.client_utils import createHistoricalNewsRequestProto, createWshMetaDataRequestProto, createCancelWshMetaDataProto, createWshEventDataRequestProto, createCancelWshEventDataProto
+from ibapi.client_utils import createScannerParametersRequestProto, createScannerSubscriptionRequestProto, createCancelScannerSubscriptionProto
+from ibapi.client_utils import createFundamentalsDataRequestProto, createCancelFundamentalsDataProto, createPnLRequestProto, createCancelPnLProto, createPnLSingleRequestProto, createCancelPnLSingleProto
+from ibapi.client_utils import createFARequestProto, createFAReplaceProto, createExerciseOptionsRequestProto
+from ibapi.client_utils import createCalculateImpliedVolatilityRequestProto, createCancelCalculateImpliedVolatilityProto, createCalculateOptionPriceRequestProto, createCancelCalculateOptionPriceProto
+from ibapi.client_utils import createSecDefOptParamsRequestProto, createSoftDollarTiersRequestProto, createFamilyCodesRequestProto, createMatchingSymbolsRequestProto
+from ibapi.client_utils import createSmartComponentsRequestProto, createMarketRuleRequestProto, createUserInfoRequestProto
+from ibapi.client_utils import createIdsRequestProto, createCurrentTimeRequestProto, createCurrentTimeInMillisRequestProto, createStartApiRequestProto
+from ibapi.client_utils import createSetServerLogLevelRequestProto, createVerifyRequestProto, createVerifyMessageRequestProto, createQueryDisplayGroupsRequestProto
+from ibapi.client_utils import createSubscribeToGroupEventsRequestProto, createUpdateDisplayGroupRequestProto, createUnsubscribeFromGroupEventsRequestProto, createMarketDepthExchangesRequestProto
+from ibapi.client_utils import createCancelContractDataProto, createCancelHistoricalTicksProto
+
+from ibapi.protobuf.ComboLeg_pb2 import ComboLeg as ComboLegProto
+from ibapi.protobuf.ExecutionFilter_pb2 import ExecutionFilter as ExecutionFilterProto
+from ibapi.protobuf.ExecutionRequest_pb2 import ExecutionRequest as ExecutionRequestProto
+from ibapi.protobuf.PlaceOrderRequest_pb2 import PlaceOrderRequest as PlaceOrderRequestProto
+from ibapi.protobuf.CancelOrderRequest_pb2 import CancelOrderRequest as CancelOrderRequestProto
+from ibapi.protobuf.GlobalCancelRequest_pb2 import GlobalCancelRequest as GlobalCancelRequestProto
+from ibapi.protobuf.AllOpenOrdersRequest_pb2 import AllOpenOrdersRequest as AllOpenOrdersRequestProto
+from ibapi.protobuf.AutoOpenOrdersRequest_pb2 import AutoOpenOrdersRequest as AutoOpenOrdersRequestProto
+from ibapi.protobuf.OpenOrdersRequest_pb2 import OpenOrdersRequest as OpenOrdersRequestProto
+from ibapi.protobuf.CompletedOrdersRequest_pb2 import CompletedOrdersRequest as CompletedOrdersRequestProto
+from ibapi.protobuf.ContractDataRequest_pb2 import ContractDataRequest as ContractDataRequestProto
+from ibapi.protobuf.MarketDataRequest_pb2 import MarketDataRequest as MarketDataRequestProto
+from ibapi.protobuf.CancelMarketData_pb2 import CancelMarketData as CancelMarketDataProto
+from ibapi.protobuf.MarketDepthRequest_pb2 import MarketDepthRequest as MarketDepthRequestProto
+from ibapi.protobuf.CancelMarketDepth_pb2 import CancelMarketDepth as CancelMarketDepthProto
+from ibapi.protobuf.MarketDataTypeRequest_pb2 import MarketDataTypeRequest as MarketDataTypeRequestProto
+from ibapi.protobuf.AccountDataRequest_pb2 import AccountDataRequest as AccountDataRequestProto
+from ibapi.protobuf.ManagedAccountsRequest_pb2 import ManagedAccountsRequest as ManagedAccountsRequestProto
+from ibapi.protobuf.PositionsRequest_pb2 import PositionsRequest as PositionsRequestProto
+from ibapi.protobuf.AccountSummaryRequest_pb2 import AccountSummaryRequest as AccountSummaryRequestProto
+from ibapi.protobuf.CancelAccountSummary_pb2 import CancelAccountSummary as CancelAccountSummaryProto
+from ibapi.protobuf.CancelPositions_pb2 import CancelPositions as CancelPositionsProto
+from ibapi.protobuf.PositionsMultiRequest_pb2 import PositionsMultiRequest as PositionsMultiRequestProto
+from ibapi.protobuf.CancelPositionsMulti_pb2 import CancelPositionsMulti as CancelPositionsMultiProto
+from ibapi.protobuf.AccountUpdatesMultiRequest_pb2 import AccountUpdatesMultiRequest as AccountUpdatesMultiRequestProto
+from ibapi.protobuf.CancelAccountUpdatesMulti_pb2 import CancelAccountUpdatesMulti as CancelAccountUpdatesMultiProto
+from ibapi.protobuf.HistoricalDataRequest_pb2 import HistoricalDataRequest as HistoricalDataRequestProto
+from ibapi.protobuf.RealTimeBarsRequest_pb2 import RealTimeBarsRequest as RealTimeBarsRequestProto
+from ibapi.protobuf.HeadTimestampRequest_pb2 import HeadTimestampRequest as HeadTimestampRequestProto
+from ibapi.protobuf.HistogramDataRequest_pb2 import HistogramDataRequest as HistogramDataRequestProto
+from ibapi.protobuf.HistoricalTicksRequest_pb2 import HistoricalTicksRequest as HistoricalTicksRequestProto
+from ibapi.protobuf.TickByTickRequest_pb2 import TickByTickRequest as TickByTickRequestProto
+from ibapi.protobuf.CancelHistoricalData_pb2 import CancelHistoricalData as CancelHistoricalDataProto
+from ibapi.protobuf.CancelRealTimeBars_pb2 import CancelRealTimeBars as CancelRealTimeBarsProto
+from ibapi.protobuf.CancelHeadTimestamp_pb2 import CancelHeadTimestamp as CancelHeadTimestampProto
+from ibapi.protobuf.CancelHistogramData_pb2 import CancelHistogramData as CancelHistogramDataProto
+from ibapi.protobuf.CancelTickByTick_pb2 import CancelTickByTick as CancelTickByTickProto
+from ibapi.protobuf.NewsBulletinsRequest_pb2 import NewsBulletinsRequest as NewsBulletinsRequestProto
+from ibapi.protobuf.CancelNewsBulletins_pb2 import CancelNewsBulletins as CancelNewsBulletinsProto
+from ibapi.protobuf.NewsArticleRequest_pb2 import NewsArticleRequest as NewsArticleRequestProto
+from ibapi.protobuf.NewsProvidersRequest_pb2 import NewsProvidersRequest as NewsProvidersRequestProto
+from ibapi.protobuf.HistoricalNewsRequest_pb2 import HistoricalNewsRequest as HistoricalNewsRequestProto
+from ibapi.protobuf.WshMetaDataRequest_pb2 import WshMetaDataRequest as WshMetaDataRequestProto
+from ibapi.protobuf.CancelWshMetaData_pb2 import CancelWshMetaData as CancelWshMetaDataProto
+from ibapi.protobuf.WshEventDataRequest_pb2 import WshEventDataRequest as WshEventDataRequestProto
+from ibapi.protobuf.CancelWshEventData_pb2 import CancelWshEventData as CancelWshEventDataProto
+from ibapi.protobuf.ScannerParametersRequest_pb2 import ScannerParametersRequest as ScannerParametersRequestProto
+from ibapi.protobuf.ScannerSubscriptionRequest_pb2 import ScannerSubscriptionRequest as ScannerSubscriptionRequestProto
+from ibapi.protobuf.ScannerSubscription_pb2 import ScannerSubscription as ScannerSubscriptionProto
+from ibapi.protobuf.FundamentalsDataRequest_pb2 import FundamentalsDataRequest as FundamentalsDataRequestProto
+from ibapi.protobuf.PnLRequest_pb2 import PnLRequest as PnLRequestProto
+from ibapi.protobuf.PnLSingleRequest_pb2 import PnLSingleRequest as PnLSingleRequestProto
+from ibapi.protobuf.CancelScannerSubscription_pb2 import CancelScannerSubscription as CancelScannerSubscriptionProto
+from ibapi.protobuf.CancelFundamentalsData_pb2 import CancelFundamentalsData as CancelFundamentalsDataProto
+from ibapi.protobuf.CancelPnL_pb2 import CancelPnL as CancelPnLProto
+from ibapi.protobuf.CancelPnLSingle_pb2 import CancelPnLSingle as CancelPnLSingleProto
+from ibapi.protobuf.FARequest_pb2 import FARequest as FARequestProto
+from ibapi.protobuf.FAReplace_pb2 import FAReplace as FAReplaceProto
+from ibapi.protobuf.ExerciseOptionsRequest_pb2 import ExerciseOptionsRequest as ExerciseOptionsRequestProto
+from ibapi.protobuf.CalculateImpliedVolatilityRequest_pb2 import CalculateImpliedVolatilityRequest as CalculateImpliedVolatilityRequestProto
+from ibapi.protobuf.CancelCalculateImpliedVolatility_pb2 import CancelCalculateImpliedVolatility as CancelCalculateImpliedVolatilityProto
+from ibapi.protobuf.CalculateOptionPriceRequest_pb2 import CalculateOptionPriceRequest as CalculateOptionPriceRequestProto
+from ibapi.protobuf.CancelCalculateOptionPrice_pb2 import CancelCalculateOptionPrice as CancelCalculateOptionPriceProto
+from ibapi.protobuf.SecDefOptParamsRequest_pb2 import SecDefOptParamsRequest as SecDefOptParamsRequestProto
+from ibapi.protobuf.SoftDollarTiersRequest_pb2 import SoftDollarTiersRequest as SoftDollarTiersRequestProto
+from ibapi.protobuf.FamilyCodesRequest_pb2 import FamilyCodesRequest as FamilyCodesRequestProto
+from ibapi.protobuf.MatchingSymbolsRequest_pb2 import MatchingSymbolsRequest as MatchingSymbolsRequestProto
+from ibapi.protobuf.SmartComponentsRequest_pb2 import SmartComponentsRequest as SmartComponentsRequestProto
+from ibapi.protobuf.MarketRuleRequest_pb2 import MarketRuleRequest as MarketRuleRequestProto
+from ibapi.protobuf.UserInfoRequest_pb2 import UserInfoRequest as UserInfoRequestProto
+from ibapi.protobuf.IdsRequest_pb2 import IdsRequest as IdsRequestProto
+from ibapi.protobuf.CurrentTimeRequest_pb2 import CurrentTimeRequest as CurrentTimeRequestProto
+from ibapi.protobuf.CurrentTimeInMillisRequest_pb2 import CurrentTimeInMillisRequest as CurrentTimeInMillisRequestProto
+from ibapi.protobuf.StartApiRequest_pb2 import StartApiRequest as StartApiRequestProto
+from ibapi.protobuf.SetServerLogLevelRequest_pb2 import SetServerLogLevelRequest as SetServerLogLevelRequestProto
+from ibapi.protobuf.VerifyRequest_pb2 import VerifyRequest as VerifyRequestProto
+from ibapi.protobuf.VerifyMessageRequest_pb2 import VerifyMessageRequest as VerifyMessageRequestProto
+from ibapi.protobuf.QueryDisplayGroupsRequest_pb2 import QueryDisplayGroupsRequest as QueryDisplayGroupsRequestProto
+from ibapi.protobuf.SubscribeToGroupEventsRequest_pb2 import SubscribeToGroupEventsRequest as SubscribeToGroupEventsRequestProto
+from ibapi.protobuf.UpdateDisplayGroupRequest_pb2 import UpdateDisplayGroupRequest as UpdateDisplayGroupRequestProto
+from ibapi.protobuf.UnsubscribeFromGroupEventsRequest_pb2 import UnsubscribeFromGroupEventsRequest as UnsubscribeFromGroupEventsRequestProto
+from ibapi.protobuf.MarketDepthExchangesRequest_pb2 import MarketDepthExchangesRequest as MarketDepthExchangesRequestProto
+from ibapi.protobuf.AttachedOrders_pb2 import AttachedOrders as AttachedOrdersProto
+from ibapi.protobuf.ConfigRequest_pb2 import ConfigRequest as ConfigRequestProto
+from ibapi.protobuf.UpdateConfigRequest_pb2 import UpdateConfigRequest as UpdateConfigRequestProto
+
+# TODO: use pylint
+
+logger = logging.getLogger(__name__)
+
+
+class EClient(object):
+ (DISCONNECTED, CONNECTING, CONNECTED) = range(3)
+
+ def __init__(self, wrapper):
+ self.msg_queue = queue.Queue()
+ self.wrapper = wrapper
+ self.decoder = None
+ self.nKeybIntHard = 0
+ self.conn = None
+ self.host = None
+ self.port = None
+ self.extraAuth = False
+ self.clientId = None
+ self.serverVersion_ = None
+ self.connTime = None
+ self.connState = None
+ self.optCapab = None
+ self.asynchronous = False
+ self.reader = None
+ self.decode = None
+ self.setConnState(EClient.DISCONNECTED)
+ self.connectOptions = None
+ self.reset()
+
+ def reset(self):
+ self.nKeybIntHard = 0
+ self.conn = None
+ self.host = None
+ self.port = None
+ self.extraAuth = False
+ self.clientId = None
+ self.serverVersion_ = None
+ self.connTime = None
+ self.connState = None
+ self.optCapab = None
+ self.asynchronous = False
+ self.reader = None
+ self.decode = None
+ self.setConnState(EClient.DISCONNECTED)
+ self.connectOptions = None
+
+ def setConnState(self, connState):
+ _connState = self.connState
+ self.connState = connState
+ logger.debug(f"{id(self)} connState: {_connState} -> {self.connState}")
+
+ def sendMsgProtoBuf(self, msgId: int, msg: bytes):
+ full_msg = comm.make_msg_proto(msgId, msg)
+ logger.info("%s %s %s", "SENDING", current_fn_name(1), full_msg)
+ self.conn.sendMsg(full_msg)
+
+ def sendMsg(self, msgId:int, msg: str):
+ useRawIntMsgId = self.serverVersion() >= MIN_SERVER_VER_PROTOBUF
+ full_msg = comm.make_msg(msgId, useRawIntMsgId, msg)
+ logger.info("%s %s %s", "SENDING", current_fn_name(1), full_msg)
+ self.conn.sendMsg(full_msg)
+
+ def logRequest(self, fnName, fnParams):
+ log_(fnName, fnParams, "REQUEST")
+
+ def validateInvalidSymbols(self, host):
+ if host is not None and not isAsciiPrintable(host):
+ raise ClientException(
+ INVALID_SYMBOL.code(),
+ INVALID_SYMBOL.msg(),
+ host.encode(sys.stdout.encoding, errors="ignore").decode(sys.stdout.encoding),
+ )
+
+ if self.connectOptions is not None and not isAsciiPrintable(self.connectOptions):
+ raise ClientException(
+ INVALID_SYMBOL.code(),
+ INVALID_SYMBOL.msg(),
+ self.connectOptions.encode(sys.stdout.encoding, errors="ignore").decode(sys.stdout.encoding),
+ )
+
+ if self.optCapab is not None and not isAsciiPrintable(self.optCapab):
+ raise ClientException(
+ INVALID_SYMBOL.code(),
+ INVALID_SYMBOL.msg(),
+ self.optCapab.encode(sys.stdout.encoding, errors="ignore").decode(sys.stdout.encoding),
+ )
+
+ def checkConnected(self):
+ if self.isConnected() :
+ raise ClientException(
+ ALREADY_CONNECTED.code(),
+ ALREADY_CONNECTED.msg(),
+ ""
+ )
+
+ def useProtoBuf(self, msgId: int) -> bool:
+ unifiedVersion = PROTOBUF_MSG_IDS.get(msgId)
+ return unifiedVersion is not None and unifiedVersion <= self.serverVersion()
+
+ def startApi(self):
+ """Initiates the message exchange between the client application and
+ the TWS/IB Gateway."""
+ if (self.useProtoBuf(OUT.START_API)):
+ startApiRequestProto = createStartApiRequestProto(self.clientId, self.optCapab)
+ self.startApiProtoBuf(startApiRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 2
+
+ msg = f"{make_field(VERSION)}{make_field(self.clientId)}"
+
+ if self.serverVersion() >= MIN_SERVER_VER_OPTIONAL_CAPABILITIES:
+ msg += make_field(self.optCapab if self.optCapab is not None else "")
+
+ self.sendMsg(OUT.START_API, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_STARTAPI.code(), FAIL_SEND_STARTAPI.msg() + str(ex))
+ return
+
+ def startApiProtoBuf(self, startApiRequestProto: StartApiRequestProto):
+ if startApiRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = startApiRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.START_API + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_STARTAPI.code(), FAIL_SEND_STARTAPI.msg() + str(ex))
+ return
+
+ def connect(self, host, port, clientId):
+ """This function must be called before any other. There is no
+ feedback for a successful connection, but a subsequent attempt to
+ connect will return the message \"Already connected.\"
+
+ host:str - The host name or IP address of the machine where TWS is
+ running. Leave blank to connect to the local host.
+ port:int - Must match the port specified in TWS on the
+ Configure>API>Socket Port field.
+ clientId:int - A number used to identify this client connection. All
+ orders placed/modified from this client will be associated with
+ this client identifier.
+
+ Note: Each client MUST connect with a unique clientId."""
+
+ try:
+ self.validateInvalidSymbols(host)
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+
+ try:
+ self.checkConnected()
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg)
+ return
+
+ try:
+ self.host = host
+ self.port = port
+ self.clientId = clientId
+ logger.debug(
+ "Connecting to %s:%d w/ id:%d", self.host, self.port, self.clientId
+ )
+
+ self.conn = Connection(self.host, self.port)
+
+ self.conn.connect()
+ self.setConnState(EClient.CONNECTING)
+
+ # TODO: support async mode
+
+ v100prefix = "API\0"
+ v100version = "v%d..%d" % (MIN_CLIENT_VER, MAX_CLIENT_VER)
+
+ if self.connectOptions:
+ v100version = v100version + " " + self.connectOptions
+
+ # v100version = "v%d..%d" % (MIN_CLIENT_VER, 101)
+ msg = comm.make_initial_msg(v100version)
+ logger.debug("msg %s", msg)
+ msg2 = str.encode(v100prefix, "ascii") + msg
+ logger.debug("REQUEST %s", msg2)
+ self.conn.sendMsg(msg2)
+
+ self.decoder = decoder.Decoder(self.wrapper, self.serverVersion())
+ fields = []
+
+ # sometimes I get news before the server version, thus the loop
+ while len(fields) != 2:
+ self.decoder.interpret(fields, 0)
+ buf = self.conn.recvMsg()
+ if not self.conn.isConnected():
+ # recvMsg() triggers disconnect() where there's a socket.error or 0 length buffer
+ # if we don't then drop out of the while loop it infinitely loops
+ logger.warning("Disconnected; resetting connection")
+ self.reset()
+ return
+ logger.debug("ANSWER %s", buf)
+ if len(buf) > 0:
+ (size, msg, rest) = comm.read_msg(buf)
+ logger.debug("size:%d msg:%s rest:%s|", size, msg, rest)
+ fields = comm.read_fields(msg)
+ logger.debug("fields %s", fields)
+ else:
+ fields = []
+
+ (server_version, conn_time) = fields
+ server_version = int(server_version)
+ logger.debug("ANSWER Version:%d time:%s", server_version, conn_time)
+ self.connTime = conn_time
+ self.serverVersion_ = server_version
+ self.decoder.serverVersion = self.serverVersion()
+
+ self.setConnState(EClient.CONNECTED)
+
+ self.reader = reader.EReader(self.conn, self.msg_queue)
+ self.reader.start() # start thread
+ logger.info("sent startApi")
+ self.startApi()
+ self.wrapper.connectAck()
+ except socket.error:
+ if self.wrapper:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), CONNECT_FAIL.code(), CONNECT_FAIL.msg())
+ logger.info("could not connect")
+ self.disconnect()
+
+ def disconnect(self):
+ """Call this function to terminate the connections with TWS.
+ Calling this function does not cancel orders that have already been
+ sent."""
+
+ self.setConnState(EClient.DISCONNECTED)
+ if self.conn is not None:
+ logger.info("disconnecting")
+ self.conn.disconnect()
+ self.wrapper.connectionClosed()
+ self.reset()
+
+ def isConnected(self):
+ """Call this function to check if there is a connection with TWS"""
+
+ connConnected = self.conn and self.conn.isConnected()
+ logger.debug(
+ f"{id(self)} isConn: {self.connState}, connConnected: {str(connConnected)}"
+ )
+ return EClient.CONNECTED == self.connState and connConnected
+
+ def keyboardInterrupt(self):
+ # intended to be overloaded
+ pass
+
+ def keyboardInterruptHard(self):
+ self.nKeybIntHard += 1
+ if self.nKeybIntHard > 5:
+ raise SystemExit()
+
+ def setConnectOptions(self, opts):
+ self.connectOptions = opts
+
+ def setOptionalCapabilities(self, optCapab):
+ self.optCapab = optCapab
+
+ def msgLoopTmo(self):
+ # intended to be overloaded
+ pass
+
+ def msgLoopRec(self):
+ # intended to be overloaded
+ pass
+
+ def run(self):
+ """This is the function that has the message loop."""
+
+ try:
+ while self.isConnected() or not self.msg_queue.empty():
+ try:
+ try:
+ text = self.msg_queue.get(block=True, timeout=0.2)
+ if len(text) > MAX_MSG_LEN:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ BAD_LENGTH.code(),
+ f"{BAD_LENGTH.msg()}:{len(text)}:{text}",
+ )
+ break
+ except queue.Empty:
+ logger.debug("queue.get: empty")
+ self.msgLoopTmo()
+ else:
+
+ if self.serverVersion() >= MIN_SERVER_VER_PROTOBUF:
+ sMsgId = text[:4]
+ msgId = int.from_bytes(sMsgId, 'big')
+ text = text[4:]
+ else:
+ sMsgId = text[:text.index(b"\0")]
+ text = text[text.index(b"\0") + len(b"\0"):]
+ msgId = int(sMsgId)
+
+ if msgId > PROTOBUF_MSG_ID:
+ msgId -= PROTOBUF_MSG_ID
+ logger.debug("msgId: %d, protobuf: %s", msgId, text)
+ self.decoder.processProtoBuf(text, msgId)
+ else:
+ fields = comm.read_fields(text)
+ logger.debug("msgId: %d, fields: %s", msgId, fields)
+ self.decoder.interpret(fields, msgId)
+
+ self.msgLoopRec()
+ except (KeyboardInterrupt, SystemExit):
+ logger.info("detected KeyboardInterrupt, SystemExit")
+ self.keyboardInterrupt()
+ self.keyboardInterruptHard()
+ except BadMessage:
+ logger.info("BadMessage")
+
+ logger.debug(
+ "conn:%d queue.sz:%d", self.isConnected(), self.msg_queue.qsize()
+ )
+ finally:
+ self.disconnect()
+
+ def reqCurrentTime(self):
+ """Asks the current system time on the server side."""
+
+ if (self.useProtoBuf(OUT.REQ_CURRENT_TIME)):
+ currentTimeRequestProto = createCurrentTimeRequestProto()
+ self.reqCurrentTimeProtoBuf(currentTimeRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = f"{make_field(VERSION)}"
+
+ self.sendMsg(OUT.REQ_CURRENT_TIME, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQCURRTIME.code(), FAIL_SEND_REQCURRTIME.msg() + str(ex))
+ return
+
+ def reqCurrentTimeProtoBuf(self, currentTimeRequestProto: CurrentTimeRequestProto):
+ if currentTimeRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = currentTimeRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_CURRENT_TIME + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQCURRTIME.code(), FAIL_SEND_REQCURRTIME.msg() + str(ex))
+ return
+
+ def serverVersion(self):
+ """Returns the version of the TWS instance to which the API application is connected."""
+
+ return self.serverVersion_
+
+ def setServerLogLevel(self, logLevel: int):
+ """The default detail level is ERROR. For more details, see API
+ Logging."""
+ if (self.useProtoBuf(OUT.SET_SERVER_LOGLEVEL)):
+ setServerLogLevelRequestProto = createSetServerLogLevelRequestProto(logLevel)
+ self.setServerLogLevelProtoBuf(setServerLogLevelRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = f"{make_field(VERSION)}{make_field(logLevel)}"
+ self.sendMsg(OUT.SET_SERVER_LOGLEVEL, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_SERVER_LOG_LEVEL.code(), FAIL_SEND_SERVER_LOG_LEVEL.msg() + str(ex))
+ return
+
+ def setServerLogLevelProtoBuf(self, setServerLogLevelRequestProto: SetServerLogLevelRequestProto):
+ if setServerLogLevelRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = setServerLogLevelRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.SET_SERVER_LOGLEVEL + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_SERVER_LOG_LEVEL.code(), FAIL_SEND_SERVER_LOG_LEVEL.msg() + str(ex))
+ return
+
+ def twsConnectionTime(self):
+ """Returns the time the API application made a connection to TWS."""
+
+ return self.connTime
+
+ ##########################################################################
+ # Market Data
+ ##########################################################################
+
+ def reqMktData(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ genericTickList: str,
+ snapshot: bool,
+ regulatorySnapshot: bool,
+ mktDataOptions: TagValueList,
+ ):
+ """Call this function to request market data. The market data
+ will be returned by the tickPrice and tickSize events.
+
+ reqId: TickerId - The ticker id. Must be a unique value. When the
+ market data returns, it will be identified by this tag. This is
+ also used when canceling the market data.
+ contract:Contract - This structure contains a description of the
+ Contractt for which market data is being requested.
+ genericTickList:str - A comma delimited list of generic tick types.
+ Tick types can be found in the Generic Tick Types page.
+ Prefixing w/ 'mdoff' indicates that top mkt data shouldn't tick.
+ You can specify the news source by postfixing w/ ':.
+ Example: "mdoff,292:FLY+BRF"
+ snapshot:bool - Check to return a single snapshot of Market data and
+ have the market data subscription cancel. Do not enter any
+ genericTicklist values if you use snapshots.
+ regulatorySnapshot: bool - With the US Value Snapshot Bundle for stocks,
+ regulatory snapshots are available for 0.01 USD each.
+ mktDataOptions:TagValueList - For internal use only.
+ Use default value XYZ."""
+
+ if (self.useProtoBuf(OUT.REQ_MKT_DATA)):
+ marketDataRequestProto = createMarketDataRequestProto(reqId, contract, genericTickList, snapshot, regulatorySnapshot, mktDataOptions)
+ self.reqMarketDataProtoBuf(marketDataRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_DELTA_NEUTRAL:
+ if contract.deltaNeutralContract:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support delta-neutral orders.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_MKT_DATA_CONID:
+ if contract.conId > 0:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support conId parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support tradingClass parameter in reqMktData.",
+ )
+ return
+
+ try:
+ VERSION = 11
+
+ # send req mkt data msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_REQ_MKT_DATA_CONID:
+ flds += [
+ make_field(contract.conId),
+ ]
+
+ flds += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier), # srv v15 and above
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange), # srv v14 and above
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ] # srv v2 and above
+
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+
+ # Send combo legs for BAG requests (srv v8 and above)
+ if contract.secType == "BAG":
+ comboLegsCount = len(contract.comboLegs) if contract.comboLegs else 0
+ flds += [
+ make_field(comboLegsCount),
+ ]
+ for comboLeg in contract.comboLegs:
+ flds += [
+ make_field(comboLeg.conId),
+ make_field(comboLeg.ratio),
+ make_field(comboLeg.action),
+ make_field(comboLeg.exchange),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_DELTA_NEUTRAL:
+ if contract.deltaNeutralContract:
+ flds += [
+ make_field(True),
+ make_field(contract.deltaNeutralContract.conId),
+ make_field(contract.deltaNeutralContract.delta),
+ make_field(contract.deltaNeutralContract.price),
+ ]
+ else:
+ flds += [
+ make_field(False),
+ ]
+
+ flds += [
+ make_field(genericTickList), # srv v31 and above
+ make_field(snapshot),
+ ] # srv v35 and above
+
+ if self.serverVersion() >= MIN_SERVER_VER_REQ_SMART_COMPONENTS:
+ flds += [
+ make_field(regulatorySnapshot),
+ ]
+
+ # send mktDataOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ # current doc says this part if for "internal use only" -> won't support it
+ if mktDataOptions:
+ raise NotImplementedError("not supported")
+ mktDataOptionsStr = ""
+ flds += [
+ make_field(mktDataOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_MKT_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMKT.code(), FAIL_SEND_REQMKT.msg() + str(ex))
+ return
+
+ def reqMarketDataProtoBuf(self, marketDataRequestProto: MarketDataRequestProto):
+ if marketDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = marketDataRequestProto.reqId if marketDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = marketDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MKT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMKT.code(), FAIL_SEND_REQMKT.msg() + str(ex))
+ return
+
+ def cancelMktData(self, reqId: TickerId):
+ """After calling this function, market data for the specified id
+ will stop flowing.
+
+ reqId: TickerId - The ID that was specified in the call to
+ reqMktData()."""
+
+ if (self.useProtoBuf(OUT.CANCEL_MKT_DATA)):
+ cancelMarketDataProto = createCancelMarketDataProto(reqId)
+ self.cancelMarketDataProtoBuf(cancelMarketDataProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 2
+
+ # send req mkt data msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.CANCEL_MKT_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANMKT.code(), FAIL_SEND_CANMKT.msg() + str(ex))
+ return
+
+
+ def cancelMarketDataProtoBuf(self, cancelMarketDataProto: CancelMarketDataProto):
+ if cancelMarketDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelMarketDataProto.reqId if cancelMarketDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelMarketDataProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_MKT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANMKT.code(), FAIL_SEND_CANMKT.msg() + str(ex))
+ return
+
+ def reqMarketDataType(self, marketDataType: int):
+ """The API can receive frozen market data from Trader
+ Workstation. Frozen market data is the last data recorded in our system.
+ During normal trading hours, the API receives real-time market data. If
+ you use this function, you are telling TWS to automatically switch to
+ frozen market data after the close. Then, before the opening of the next
+ trading day, market data will automatically switch back to real-time
+ market data.
+
+ marketDataType:int - 1 for real-time streaming market data or 2 for
+ frozen market data"""
+
+ if (self.useProtoBuf(OUT.REQ_MARKET_DATA_TYPE)):
+ marketDataTypeRequestProto = createMarketDataTypeRequestProto(marketDataType)
+ self.reqMarketDataTypeProtoBuf(marketDataTypeRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_MARKET_DATA_TYPE:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support market data type requests.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ # send req mkt data msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(marketDataType),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_MARKET_DATA_TYPE, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQMARKETDATATYPE.code(), FAIL_SEND_REQMARKETDATATYPE.msg() + str(ex))
+ return
+
+ def reqMarketDataTypeProtoBuf(self, marketDataTypeRequestProto: MarketDataTypeRequestProto):
+ if marketDataTypeRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = marketDataTypeRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MARKET_DATA_TYPE + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQMARKETDATATYPE.code(), FAIL_SEND_REQMARKETDATATYPE.msg() + str(ex))
+ return
+
+ def reqSmartComponents(self, reqId: int, bboExchange: str):
+ if self.useProtoBuf(OUT.REQ_SMART_COMPONENTS):
+ self.reqSmartComponentsProtoBuf(createSmartComponentsRequestProto(reqId, bboExchange))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_SMART_COMPONENTS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support smart components request.",
+ )
+ return
+
+ try:
+ msg = (
+ make_field(reqId)
+ + make_field(bboExchange)
+ )
+ self.sendMsg(OUT.REQ_SMART_COMPONENTS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSMARTCOMPONENTS.code(), FAIL_SEND_REQSMARTCOMPONENTS.msg() + str(ex))
+ return
+
+ def reqSmartComponentsProtoBuf(self, smartComponentsRequestProto: SmartComponentsRequestProto):
+ if smartComponentsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = smartComponentsRequestProto.reqId if smartComponentsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = smartComponentsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_SMART_COMPONENTS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSMARTCOMPONENTS.code(), FAIL_SEND_REQSMARTCOMPONENTS.msg() + str(ex))
+ return
+
+ def reqMarketRule(self, marketRuleId: int):
+ if self.useProtoBuf(OUT.REQ_MARKET_RULE):
+ self.reqMarketRuleProtoBuf(createMarketRuleRequestProto(marketRuleId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MARKET_RULES:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support market rule requests.",
+ )
+ return
+
+ try:
+ msg = make_field(marketRuleId)
+ self.sendMsg(OUT.REQ_MARKET_RULE, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQMARKETRULE.code(), FAIL_SEND_REQMARKETRULE.msg() + str(ex))
+ return
+
+ def reqMarketRuleProtoBuf(self, marketRuleRequestProto: MarketRuleRequestProto):
+ if marketRuleRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = marketRuleRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MARKET_RULE + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQMARKETRULE.code(), FAIL_SEND_REQMARKETRULE.msg() + str(ex))
+ return
+
+ def reqTickByTickData(
+ self,
+ reqId: int,
+ contract: Contract,
+ tickType: str,
+ numberOfTicks: int,
+ ignoreSize: bool,
+ ):
+ if self.useProtoBuf(OUT.REQ_TICK_BY_TICK_DATA):
+ tickByTickRequestProto = createTickByTickRequestProto(reqId, contract, tickType, numberOfTicks, ignoreSize)
+ self.reqTickByTickDataProtoBuf(tickByTickRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TICK_BY_TICK:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support tick-by-tick data requests.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support ignoreSize and numberOfTicks parameters "
+ "in tick-by-tick data requests.",
+ )
+ return
+
+ try:
+ msg = (
+ make_field(reqId)
+ + make_field(contract.conId)
+ + make_field(contract.symbol)
+ + make_field(contract.secType)
+ + make_field(contract.lastTradeDateOrContractMonth)
+ + make_field_handle_empty(contract.strike)
+ + make_field(contract.right)
+ + make_field(contract.multiplier)
+ + make_field(contract.exchange)
+ + make_field(contract.primaryExchange)
+ + make_field(contract.currency)
+ + make_field(contract.localSymbol)
+ + make_field(contract.tradingClass)
+ + make_field(tickType)
+ )
+
+ if self.serverVersion() >= MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE:
+ msg += make_field(numberOfTicks) + make_field(ignoreSize)
+ self.sendMsg(OUT.REQ_TICK_BY_TICK_DATA, msg)
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQTICKBYTICKDATA.code(), FAIL_SEND_REQTICKBYTICKDATA.msg() + str(ex))
+ return
+
+ def reqTickByTickDataProtoBuf(self, tickByTickRequestProto: TickByTickRequestProto):
+ if tickByTickRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = tickByTickRequestProto.reqId if tickByTickRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = tickByTickRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_TICK_BY_TICK_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQTICKBYTICKDATA.code(), FAIL_SEND_REQTICKBYTICKDATA.msg() + str(ex))
+ return
+
+ def cancelTickByTickData(self, reqId: int):
+ if self.useProtoBuf(OUT.CANCEL_TICK_BY_TICK_DATA):
+ cancelTickByTickProto = createCancelTickByTickProto(reqId)
+ self.cancelTickByTickProtoBuf(cancelTickByTickProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TICK_BY_TICK:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support tick-by-tick data requests.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.CANCEL_TICK_BY_TICK_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELTICKBYTICKDATA.code(), FAIL_SEND_CANCELTICKBYTICKDATA.msg() + str(ex))
+ return
+
+ def cancelTickByTickProtoBuf(self, cancelTickByTickProto: CancelTickByTickProto):
+ if cancelTickByTickProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelTickByTickProto.reqId if cancelTickByTickProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelTickByTickProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_TICK_BY_TICK_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELTICKBYTICKDATA.code(), FAIL_SEND_CANCELTICKBYTICKDATA.msg() + str(ex))
+ return
+
+ ##########################################################################
+ # Options
+ ##########################################################################
+
+ def calculateImpliedVolatility(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ optionPrice: float,
+ underPrice: float,
+ implVolOptions: TagValueList,
+ ):
+ """Call this function to calculate volatility for a supplied
+ option price and underlying price. Result will be delivered
+ via EWrapper.tickOptionComputation()
+
+ reqId:TickerId - The request id.
+ contract:Contract - Describes the contract.
+ optionPrice:double - The price of the option.
+ underPrice:double - Price of the underlying."""
+
+ if (self.useProtoBuf(OUT.REQ_CALC_IMPLIED_VOLAT)):
+ calculateImpliedVolatilityRequestProto = createCalculateImpliedVolatilityRequestProto(reqId, contract, optionPrice, underPrice, implVolOptions)
+ self.calculateImpliedVolatilityProtoBuf(calculateImpliedVolatilityRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support calculateImpliedVolatility req.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support tradingClass parameter in calculateImpliedVolatility.",
+ )
+ return
+
+ try:
+ VERSION = 3
+
+ # send req mkt data msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ # send contract fields
+ make_field(contract.conId),
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+ flds += [make_field(optionPrice), make_field(underPrice)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ implVolOptStr = ""
+ if implVolOptions:
+ raise NotImplementedError("not supported")
+ flds += [
+ make_field(implVolOptStr)
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_CALC_IMPLIED_VOLAT, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCALCIMPLIEDVOLAT.code(), FAIL_SEND_REQCALCIMPLIEDVOLAT.msg() + str(ex))
+ return
+
+ def calculateImpliedVolatilityProtoBuf(self, calculateImpliedVolatilityRequestProto: CalculateImpliedVolatilityRequestProto):
+ if calculateImpliedVolatilityRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = calculateImpliedVolatilityRequestProto.reqId if calculateImpliedVolatilityRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = calculateImpliedVolatilityRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_CALC_IMPLIED_VOLAT + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCALCIMPLIEDVOLAT.code(), FAIL_SEND_REQCALCIMPLIEDVOLAT.msg() + str(ex))
+ return
+
+ def cancelCalculateImpliedVolatility(self, reqId: TickerId):
+ """Call this function to cancel a request to calculate
+ volatility for a supplied option price and underlying price.
+
+ reqId:TickerId - The request ID."""
+
+ if (self.useProtoBuf(OUT.CANCEL_CALC_IMPLIED_VOLAT)):
+ cancelCalculateImpliedVolatilityProto = createCancelCalculateImpliedVolatilityProto(reqId)
+ self.cancelCalculateImpliedVolatilityProtoBuf(cancelCalculateImpliedVolatilityProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support calculateImpliedVolatility req.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.CANCEL_CALC_IMPLIED_VOLAT, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCALCIMPLIEDVOLAT.code(), FAIL_SEND_CANCALCIMPLIEDVOLAT.msg() + str(ex))
+ return
+
+ def cancelCalculateImpliedVolatilityProtoBuf(self, cancelCalculateImpliedVolatilityProto: CancelCalculateImpliedVolatilityProto):
+ if cancelCalculateImpliedVolatilityProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelCalculateImpliedVolatilityProto.reqId if cancelCalculateImpliedVolatilityProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelCalculateImpliedVolatilityProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_CALC_IMPLIED_VOLAT + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCALCIMPLIEDVOLAT.code(), FAIL_SEND_CANCALCIMPLIEDVOLAT.msg() + str(ex))
+ return
+
+ def calculateOptionPrice(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ volatility: float,
+ underPrice: float,
+ optPrcOptions: TagValueList,
+ ):
+ """Call this function to calculate option price and greek values
+ for a supplied volatility and underlying price.
+
+ reqId:TickerId - The ticker ID.
+ contract:Contract - Describes the contract.
+ volatility:double - The volatility.
+ underPrice:double - Price of the underlying."""
+
+ if (self.useProtoBuf(OUT.REQ_CALC_OPTION_PRICE)):
+ calculateOptionPriceRequestProto = createCalculateOptionPriceRequestProto(reqId, contract, volatility, underPrice, optPrcOptions)
+ self.calculateOptionPriceProtoBuf(calculateOptionPriceRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support calculateImpliedVolatility req.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support tradingClass parameter in calculateImpliedVolatility.",
+ )
+ return
+
+ try:
+ VERSION = 3
+
+ # send req mkt data msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ # send contract fields
+ make_field(contract.conId),
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+ flds += [make_field(volatility), make_field(underPrice)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ optPrcOptStr = ""
+ if optPrcOptions:
+ raise NotImplementedError("not supported")
+ flds += [
+ make_field(optPrcOptStr)
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_CALC_OPTION_PRICE, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCALCOPTIONPRICE.code(), FAIL_SEND_REQCALCOPTIONPRICE.msg() + str(ex))
+ return
+
+ def calculateOptionPriceProtoBuf(self, calculateOptionPriceRequestProto: CalculateOptionPriceRequestProto):
+ if calculateOptionPriceRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = calculateOptionPriceRequestProto.reqId if calculateOptionPriceRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = calculateOptionPriceRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_CALC_OPTION_PRICE + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCALCOPTIONPRICE.code(), FAIL_SEND_REQCALCOPTIONPRICE.msg() + str(ex))
+ return
+
+ def cancelCalculateOptionPrice(self, reqId: TickerId):
+ """Call this function to cancel a request to calculate the option
+ price and greek values for a supplied volatility and underlying price.
+
+ reqId:TickerId - The request ID."""
+
+ if (self.useProtoBuf(OUT.CANCEL_CALC_OPTION_PRICE)):
+ cancelCalculateOptionPriceProto = createCancelCalculateOptionPriceProto(reqId)
+ self.cancelCalculateOptionPriceProtoBuf(cancelCalculateOptionPriceProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support calculateImpliedVolatility req.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.CANCEL_CALC_OPTION_PRICE, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCALCOPTIONPRICE.code(), FAIL_SEND_CANCALCOPTIONPRICE.msg() + str(ex))
+ return
+
+ def cancelCalculateOptionPriceProtoBuf(self, cancelCalculateOptionPriceProto: CancelCalculateOptionPriceProto):
+ if cancelCalculateOptionPriceProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelCalculateOptionPriceProto.reqId if cancelCalculateOptionPriceProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelCalculateOptionPriceProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_CALC_OPTION_PRICE + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCALCOPTIONPRICE.code(), FAIL_SEND_CANCALCOPTIONPRICE.msg() + str(ex))
+ return
+
+ def exerciseOptions(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ exerciseAction: int,
+ exerciseQuantity: int,
+ account: str,
+ override: int,
+ manualOrderTime: str,
+ customerAccount: str,
+ professionalCustomer: bool
+ ):
+ """reqId:TickerId - The ticker id. multipleust be a unique value.
+ contract:Contract - This structure contains a description of the
+ contract to be exercised
+ exerciseAction:int - Specifies whether you want the option to lapse
+ or be exercised.
+ Values are 1 = exercise, 2 = lapse.
+ exerciseQuantity:int - The quantity you want to exercise.
+ account:str - destination account
+ override:int - Specifies whether your setting will override the system's
+ natural action. For example, if your action is "exercise" and the
+ option is not in-the-money, by natural action the option would not
+ exercise. If you have override set to "yes" the natural action would
+ be overridden and the out-of-the money option would be exercised.
+ Values are: 0 = no, 1 = yes.
+ manualOrderTime:str - manual order time
+ customerAccount:str - customer account
+ professionalCustomer:bool - professional customer"""
+
+ if (self.useProtoBuf(OUT.EXERCISE_OPTIONS)):
+ exerciseOptionsRequestProto = createExerciseOptionsRequestProto(reqId, contract, exerciseAction, exerciseQuantity, account, override != 0, manualOrderTime, customerAccount, professionalCustomer)
+ self.exerciseOptionsProtoBuf(exerciseOptionsRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass or contract.conId > 0:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support conId and tradingClass parameters in exerciseOptions.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MANUAL_ORDER_TIME_EXERCISE_OPTIONS and manualOrderTime:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support manual order time parameter in exerciseOptions.",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_CUSTOMER_ACCOUNT
+ and customerAccount
+ ):
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support customer account parameter in exerciseOptions.",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_PROFESSIONAL_CUSTOMER
+ and professionalCustomer
+ ):
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support professional customer parameter in exerciseOptions.",
+ )
+ return
+
+ try:
+ VERSION = 2
+
+ # send req mkt data msg
+ fields = []
+ fields += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ fields += [
+ make_field(contract.conId),
+ ]
+ fields += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ fields += [
+ make_field(contract.tradingClass),
+ ]
+ fields += [
+ make_field(exerciseAction),
+ make_field(exerciseQuantity),
+ make_field(account),
+ make_field(override),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_MANUAL_ORDER_TIME_EXERCISE_OPTIONS:
+ fields += [
+ make_field(manualOrderTime),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_CUSTOMER_ACCOUNT:
+ fields += [
+ make_field(customerAccount),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_PROFESSIONAL_CUSTOMER:
+ fields += [
+ make_field(professionalCustomer),
+ ]
+
+ msg = "".join(fields)
+ self.sendMsg(OUT.EXERCISE_OPTIONS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMKT.code(), FAIL_SEND_REQMKT.msg() + str(ex))
+ return
+
+ def exerciseOptionsProtoBuf(self, exerciseOptionsRequestProto: ExerciseOptionsRequestProto):
+ if exerciseOptionsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ orderId = exerciseOptionsRequestProto.orderId if exerciseOptionsRequestProto.HasField('orderId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(orderId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = exerciseOptionsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.EXERCISE_OPTIONS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), FAIL_SEND_REQMKT.code(), FAIL_SEND_REQMKT.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Orders
+ ########################################################################
+
+ def placeOrder(self, orderId: OrderId, contract: Contract, order: Order):
+ """Call this function to place an order. The order status will
+ be returned by the orderStatus event.
+
+ orderId:OrderId - The order id. You must specify a unique value. When the
+ order START_APItus returns, it will be identified by this tag.
+ This tag is also used when canceling the order.
+ contract:Contract - This structure contains a description of the
+ contract which is being traded.
+ order:Order - This structure contains the details of tradedhe order.
+ Note: Each client MUST connect with a unique clientId."""
+
+ if (self.useProtoBuf(OUT.PLACE_ORDER)):
+ placeOrderRequestProto = createPlaceOrderRequestProto(orderId, contract, order)
+ self.placeOrderProtoBuf(placeOrderRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(orderId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_DELTA_NEUTRAL:
+ if contract.deltaNeutralContract:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support delta-neutral orders.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SCALE_ORDERS2:
+ if order.scaleSubsLevelSize != UNSET_INTEGER:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support Subsequent Level Size for Scale orders.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_ALGO_ORDERS:
+ if order.algoStrategy:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support algo orders.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_NOT_HELD:
+ if order.notHeld:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support notHeld parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SEC_ID_TYPE:
+ if contract.secIdType or contract.secId:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support secIdType and secId parameters.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_PLACE_ORDER_CONID:
+ if contract.conId and contract.conId > 0:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support conId parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SSHORTX:
+ if order.exemptCode != -1:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support exemptCode parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SSHORTX:
+ if contract.comboLegs:
+ for comboLeg in contract.comboLegs:
+ if comboLeg.exemptCode != -1:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support exemptCode parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_HEDGE_ORDERS:
+ if order.hedgeType:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support hedge orders.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_OPT_OUT_SMART_ROUTING:
+ if order.optOutSmartRouting:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support optOutSmartRouting parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_DELTA_NEUTRAL_CONID:
+ if (
+ order.deltaNeutralConId > 0
+ or order.deltaNeutralSettlingFirm
+ or order.deltaNeutralClearingAccount
+ or order.deltaNeutralClearingIntent
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support deltaNeutral parameters: "
+ + "ConId, SettlingFirm, ClearingAccount, ClearingIntent.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE:
+ if (
+ order.deltaNeutralOpenClose
+ or order.deltaNeutralShortSale
+ or order.deltaNeutralShortSaleSlot > 0
+ or order.deltaNeutralDesignatedLocation
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support deltaNeutral parameters: "
+ "OpenClose, ShortSale, ShortSaleSlot, DesignatedLocation.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SCALE_ORDERS3:
+ if (
+ order.scalePriceIncrement > 0
+ and order.scalePriceIncrement != UNSET_DOUBLE
+ ):
+ if (
+ order.scalePriceAdjustValue != UNSET_DOUBLE
+ or order.scalePriceAdjustInterval != UNSET_INTEGER
+ or order.scaleProfitOffset != UNSET_DOUBLE
+ or order.scaleAutoReset
+ or order.scaleInitPosition != UNSET_INTEGER
+ or order.scaleInitFillQty != UNSET_INTEGER
+ or order.scaleRandomPercent
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, "
+ + "ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE
+ and contract.secType == "BAG"
+ ):
+ if order.orderComboLegs:
+ for orderComboLeg in order.orderComboLegs:
+ if orderComboLeg.price != UNSET_DOUBLE:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support per-leg prices for order combo legs.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRAILING_PERCENT:
+ if order.trailingPercent != UNSET_DOUBLE:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support trailing percent parameter",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support tradingClass parameter in placeOrder.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SCALE_TABLE:
+ if order.scaleTable or order.activeStartTime or order.activeStopTime:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support scaleTable, activeStartTime and activeStopTime parameters",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_ALGO_ID:
+ if order.algoId:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support algoId parameter",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_ORDER_SOLICITED:
+ if order.solicited:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support order solicited parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MODELS_SUPPORT:
+ if order.modelCode:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support model code parameter.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_EXT_OPERATOR:
+ if order.extOperator:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support ext operator parameter",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SOFT_DOLLAR_TIER:
+ if order.softDollarTier.name or order.softDollarTier.val:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support soft dollar tier",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CASH_QTY:
+ if order.cashQty:
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support cash quantity parameter",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_DECISION_MAKER and (
+ order.mifid2DecisionMaker != "" or order.mifid2DecisionAlgo != ""
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support MIFID II decision maker parameters",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MIFID_EXECUTION and (
+ order.mifid2ExecutionTrader != "" or order.mifid2ExecutionAlgo != ""
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support MIFID II execution parameters",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE
+ and order.dontUseAutoPriceForHedge
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support dontUseAutoPriceForHedge parameter",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_ORDER_CONTAINER
+ and order.isOmsContainer
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support oms container parameter",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_PRICE_MGMT_ALGO
+ and order.usePriceMgmtAlgo
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support Use price management algo requests",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_DURATION
+ and order.duration != UNSET_INTEGER
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support duration attribute",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_POST_TO_ATS
+ and order.postToAts != UNSET_INTEGER
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support postToAts attribute",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_AUTO_CANCEL_PARENT
+ and order.autoCancelParent
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support autoCancelParent attribute",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_ADVANCED_ORDER_REJECT
+ and order.advancedErrorOverride
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support advanced error override attribute",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_MANUAL_ORDER_TIME
+ and order.manualOrderTime
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support manual order time attribute",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS:
+ if (
+ order.minTradeQty != UNSET_INTEGER
+ or order.minCompeteSize != UNSET_INTEGER
+ or order.competeAgainstBestOffset != UNSET_DOUBLE
+ or order.midOffsetAtWhole != UNSET_DOUBLE
+ or order.midOffsetAtHalf != UNSET_DOUBLE
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support PEG BEST / PEG MID order parameters: minTradeQty, minCompeteSize, "
+ + "competeAgainstBestOffset, midOffsetAtWhole and midOffsetAtHalf",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_CUSTOMER_ACCOUNT
+ and order.customerAccount
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support customer account parameter",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_PROFESSIONAL_CUSTOMER
+ and order.professionalCustomer
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support professional customer parameter",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_INCLUDE_OVERNIGHT
+ and order.includeOvernight
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support include overnight parameter",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_CME_TAGGING_FIELDS
+ and order.manualOrderIndicator != UNSET_INTEGER
+ ):
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support manual order indicator parameters",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_IMBALANCE_ONLY
+ and order.imbalanceOnly
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support imbalance only parameter",
+ )
+ return
+
+ try:
+ VERSION = 27 if (self.serverVersion() < MIN_SERVER_VER_NOT_HELD) else 45
+
+ # send place order msg
+ flds = []
+
+ if self.serverVersion() < MIN_SERVER_VER_ORDER_CONTAINER:
+ flds += [make_field(VERSION)]
+
+ flds += [make_field(orderId)]
+
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_PLACE_ORDER_CONID:
+ flds.append(make_field(contract.conId))
+ flds += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier), # srv v15 and above
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange), # srv v14 and above
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ] # srv v2 and above
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds.append(make_field(contract.tradingClass))
+
+ if self.serverVersion() >= MIN_SERVER_VER_SEC_ID_TYPE:
+ flds += [make_field(contract.secIdType), make_field(contract.secId)]
+
+ # send main order fields
+ flds.append(make_field(order.action))
+
+ if self.serverVersion() >= MIN_SERVER_VER_FRACTIONAL_POSITIONS:
+ flds.append(make_field(order.totalQuantity))
+ else:
+ flds.append(make_field(int(order.totalQuantity)))
+
+ flds.append(make_field(order.orderType))
+ if self.serverVersion() < MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE:
+ flds.append(
+ make_field(order.lmtPrice if order.lmtPrice != UNSET_DOUBLE else 0)
+ )
+ else:
+ flds.append(make_field_handle_empty(order.lmtPrice))
+ if self.serverVersion() < MIN_SERVER_VER_TRAILING_PERCENT:
+ flds.append(
+ make_field(order.auxPrice if order.auxPrice != UNSET_DOUBLE else 0)
+ )
+ else:
+ flds.append(make_field_handle_empty(order.auxPrice))
+
+ # send extended order fields
+ flds += [
+ make_field(order.tif),
+ make_field(order.ocaGroup),
+ make_field(order.account),
+ make_field(order.openClose),
+ make_field(order.origin),
+ make_field(order.orderRef),
+ make_field(order.transmit),
+ make_field(order.parentId), # srv v4 and above
+ make_field(order.blockOrder), # srv v5 and above
+ make_field(order.sweepToFill), # srv v5 and above
+ make_field(order.displaySize), # srv v5 and above
+ make_field(order.triggerMethod), # srv v5 and above
+ make_field(order.outsideRth), # srv v5 and above
+ make_field(order.hidden),
+ ] # srv v7 and above
+
+ # Send combo legs for BAG requests (srv v8 and above)
+ if contract.secType == "BAG":
+ comboLegsCount = len(contract.comboLegs) if contract.comboLegs else 0
+ flds.append(make_field(comboLegsCount))
+ if comboLegsCount > 0:
+ for comboLeg in contract.comboLegs:
+ assert comboLeg
+ flds += [
+ make_field(comboLeg.conId),
+ make_field(comboLeg.ratio),
+ make_field(comboLeg.action),
+ make_field(comboLeg.exchange),
+ make_field(comboLeg.openClose),
+ make_field(comboLeg.shortSaleSlot), # srv v35 and above
+ make_field(comboLeg.designatedLocation),
+ ] # srv v35 and above
+ if self.serverVersion() >= MIN_SERVER_VER_SSHORTX_OLD:
+ flds.append(make_field(comboLeg.exemptCode))
+
+ # Send order combo legs for BAG requests
+ if (
+ self.serverVersion() >= MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE
+ and contract.secType == "BAG"
+ ):
+ orderComboLegsCount = (
+ len(order.orderComboLegs) if order.orderComboLegs else 0
+ )
+ flds.append(make_field(orderComboLegsCount))
+ if orderComboLegsCount:
+ for orderComboLeg in order.orderComboLegs:
+ assert orderComboLeg
+ flds.append(make_field_handle_empty(orderComboLeg.price))
+
+ if (
+ self.serverVersion() >= MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS
+ and contract.secType == "BAG"
+ ):
+ smartComboRoutingParamsCount = (
+ len(order.smartComboRoutingParams)
+ if order.smartComboRoutingParams
+ else 0
+ )
+ flds.append(make_field(smartComboRoutingParamsCount))
+ if smartComboRoutingParamsCount > 0:
+ for tagValue in order.smartComboRoutingParams:
+ flds += [make_field(tagValue.tag), make_field(tagValue.value)]
+
+ ######################################################################
+ # Send the shares allocation.
+ #
+ # This specifies the number of order shares allocated to each Financial
+ # Advisor managed account. The format of the allocation string is as
+ # follows:
+ # /,/,...N
+ # E.g.
+ # To allocate 20 shares of a 100 share order to account 'U101' and the
+ # residual 80 to account 'U203' enter the following share allocation string:
+ # U101/20,U203/80
+ #####################################################################
+ # send deprecated sharesAllocation field
+ flds += [
+ make_field(""), # srv v9 and above
+ make_field(order.discretionaryAmt), # srv v10 and above
+ make_field(order.goodAfterTime), # srv v11 and above
+ make_field(order.goodTillDate), # srv v12 and above
+ make_field(order.faGroup), # srv v13 and above
+ make_field(order.faMethod), # srv v13 and above
+ make_field(order.faPercentage),
+ ] # srv v13 and above
+ if self.serverVersion() < MIN_SERVER_VER_FA_PROFILE_DESUPPORT:
+ flds.append(make_field("")) # send deprecated faProfile field
+
+ if self.serverVersion() >= MIN_SERVER_VER_MODELS_SUPPORT:
+ flds.append(make_field(order.modelCode))
+
+ # institutional short saleslot data (srv v18 and above)
+ flds += [
+ make_field(
+ order.shortSaleSlot
+ ), # 0 for retail, 1 or 2 for institutions
+ make_field(order.designatedLocation),
+ ] # populate only when shortSaleSlot = 2.
+ if self.serverVersion() >= MIN_SERVER_VER_SSHORTX_OLD:
+ flds.append(make_field(order.exemptCode))
+
+ # srv v19 and above fields
+ flds.append(make_field(order.ocaType))
+ # if( self.serverVersion() < 38) {
+ # will never happen
+ # send( /* order.rthOnly */ false)
+ # }
+ flds += [
+ make_field(order.rule80A),
+ make_field(order.settlingFirm),
+ make_field(order.allOrNone),
+ make_field_handle_empty(order.minQty),
+ make_field_handle_empty(order.percentOffset),
+ make_field(False),
+ make_field(False),
+ make_field_handle_empty(UNSET_DOUBLE),
+ make_field(
+ order.auctionStrategy
+ ), # AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT
+ make_field_handle_empty(order.startingPrice),
+ make_field_handle_empty(order.stockRefPrice),
+ make_field_handle_empty(order.delta),
+ make_field_handle_empty(order.stockRangeLower),
+ make_field_handle_empty(order.stockRangeUpper),
+ make_field(order.overridePercentageConstraints), # srv v22 and above
+ # Volatility orders (srv v26 and above)
+ make_field_handle_empty(order.volatility),
+ make_field_handle_empty(order.volatilityType),
+ make_field(order.deltaNeutralOrderType), # srv v28 and above
+ make_field_handle_empty(order.deltaNeutralAuxPrice),
+ ] # srv v28 and above
+
+ if (
+ self.serverVersion() >= MIN_SERVER_VER_DELTA_NEUTRAL_CONID
+ and order.deltaNeutralOrderType
+ ):
+ flds += [
+ make_field(order.deltaNeutralConId),
+ make_field(order.deltaNeutralSettlingFirm),
+ make_field(order.deltaNeutralClearingAccount),
+ make_field(order.deltaNeutralClearingIntent),
+ ]
+
+ if (
+ self.serverVersion() >= MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE
+ and order.deltaNeutralOrderType
+ ):
+ flds += [
+ make_field(order.deltaNeutralOpenClose),
+ make_field(order.deltaNeutralShortSale),
+ make_field(order.deltaNeutralShortSaleSlot),
+ make_field(order.deltaNeutralDesignatedLocation),
+ ]
+
+ flds += [
+ make_field(order.continuousUpdate),
+ make_field_handle_empty(order.referencePriceType),
+ make_field_handle_empty(order.trailStopPrice),
+ ] # srv v30 and above
+
+ if self.serverVersion() >= MIN_SERVER_VER_TRAILING_PERCENT:
+ flds.append(make_field_handle_empty(order.trailingPercent))
+
+ # SCALE orders
+ if self.serverVersion() >= MIN_SERVER_VER_SCALE_ORDERS2:
+ flds += [
+ make_field_handle_empty(order.scaleInitLevelSize),
+ make_field_handle_empty(order.scaleSubsLevelSize),
+ ]
+ else:
+ # srv v35 and above)
+ flds += [
+ make_field(""), # for not supported scaleNumComponents
+ make_field_handle_empty(order.scaleInitLevelSize),
+ ] # for scaleComponentSize
+
+ flds.append(make_field_handle_empty(order.scalePriceIncrement))
+
+ if (
+ self.serverVersion() >= MIN_SERVER_VER_SCALE_ORDERS3
+ and order.scalePriceIncrement != UNSET_DOUBLE
+ and order.scalePriceIncrement > 0.0
+ ):
+ flds += [
+ make_field_handle_empty(order.scalePriceAdjustValue),
+ make_field_handle_empty(order.scalePriceAdjustInterval),
+ make_field_handle_empty(order.scaleProfitOffset),
+ make_field(order.scaleAutoReset),
+ make_field_handle_empty(order.scaleInitPosition),
+ make_field_handle_empty(order.scaleInitFillQty),
+ make_field(order.scaleRandomPercent),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_SCALE_TABLE:
+ flds += [
+ make_field(order.scaleTable),
+ make_field(order.activeStartTime),
+ make_field(order.activeStopTime),
+ ]
+
+ # HEDGE orders
+ if self.serverVersion() >= MIN_SERVER_VER_HEDGE_ORDERS:
+ flds.append(make_field(order.hedgeType))
+ if order.hedgeType:
+ flds.append(make_field(order.hedgeParam))
+
+ if self.serverVersion() >= MIN_SERVER_VER_OPT_OUT_SMART_ROUTING:
+ flds.append(make_field(order.optOutSmartRouting))
+
+ if self.serverVersion() >= MIN_SERVER_VER_PTA_ORDERS:
+ flds += [
+ make_field(order.clearingAccount),
+ make_field(order.clearingIntent),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_NOT_HELD:
+ flds.append(make_field(order.notHeld))
+
+ if self.serverVersion() >= MIN_SERVER_VER_DELTA_NEUTRAL:
+ if contract.deltaNeutralContract:
+ flds += [
+ make_field(True),
+ make_field(contract.deltaNeutralContract.conId),
+ make_field(contract.deltaNeutralContract.delta),
+ make_field(contract.deltaNeutralContract.price),
+ ]
+ else:
+ flds.append(make_field(False))
+
+ if self.serverVersion() >= MIN_SERVER_VER_ALGO_ORDERS:
+ flds.append(make_field(order.algoStrategy))
+ if order.algoStrategy:
+ algoParamsCount = len(order.algoParams) if order.algoParams else 0
+ flds.append(make_field(algoParamsCount))
+ if algoParamsCount > 0:
+ for algoParam in order.algoParams:
+ flds += [
+ make_field(algoParam.tag),
+ make_field(algoParam.value),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_ALGO_ID:
+ flds.append(make_field(order.algoId))
+
+ flds.append(make_field(order.whatIf)) # srv v36 and above
+
+ # send miscOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ miscOptionsStr = ""
+ if order.orderMiscOptions:
+ for tagValue in order.orderMiscOptions:
+ miscOptionsStr += str(tagValue)
+ flds.append(make_field(miscOptionsStr))
+
+ if self.serverVersion() >= MIN_SERVER_VER_ORDER_SOLICITED:
+ flds.append(make_field(order.solicited))
+
+ if self.serverVersion() >= MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE:
+ flds += [
+ make_field(order.randomizeSize),
+ make_field(order.randomizePrice),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK:
+ if isPegBenchOrder(order.orderType):
+ flds += [
+ make_field(order.referenceContractId),
+ make_field(order.isPeggedChangeAmountDecrease),
+ make_field(order.peggedChangeAmount),
+ make_field(order.referenceChangeAmount),
+ make_field(order.referenceExchangeId),
+ ]
+
+ flds.append(make_field(len(order.conditions)))
+
+ if len(order.conditions) > 0:
+ for cond in order.conditions:
+ flds.append(make_field(cond.type()))
+ flds += cond.make_fields()
+
+ flds += [
+ make_field(order.conditionsIgnoreRth),
+ make_field(order.conditionsCancelOrder),
+ ]
+
+ flds += [
+ make_field(order.adjustedOrderType),
+ make_field(order.triggerPrice),
+ make_field(order.lmtPriceOffset),
+ make_field(order.adjustedStopPrice),
+ make_field(order.adjustedStopLimitPrice),
+ make_field(order.adjustedTrailingAmount),
+ make_field(order.adjustableTrailingUnit),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_EXT_OPERATOR:
+ flds.append(make_field(order.extOperator))
+
+ if self.serverVersion() >= MIN_SERVER_VER_SOFT_DOLLAR_TIER:
+ flds += [
+ make_field(order.softDollarTier.name),
+ make_field(order.softDollarTier.val),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_CASH_QTY:
+ flds.append(make_field(order.cashQty))
+
+ if self.serverVersion() >= MIN_SERVER_VER_DECISION_MAKER:
+ flds.append(make_field(order.mifid2DecisionMaker))
+ flds.append(make_field(order.mifid2DecisionAlgo))
+
+ if self.serverVersion() >= MIN_SERVER_VER_MIFID_EXECUTION:
+ flds.append(make_field(order.mifid2ExecutionTrader))
+ flds.append(make_field(order.mifid2ExecutionAlgo))
+
+ if self.serverVersion() >= MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE:
+ flds.append(make_field(order.dontUseAutoPriceForHedge))
+
+ if self.serverVersion() >= MIN_SERVER_VER_ORDER_CONTAINER:
+ flds.append(make_field(order.isOmsContainer))
+
+ if self.serverVersion() >= MIN_SERVER_VER_D_PEG_ORDERS:
+ flds.append(make_field(order.discretionaryUpToLimitPrice))
+
+ if self.serverVersion() >= MIN_SERVER_VER_PRICE_MGMT_ALGO:
+ flds.append(
+ make_field_handle_empty(
+ UNSET_INTEGER
+ if order.usePriceMgmtAlgo is None
+ else 1
+ if order.usePriceMgmtAlgo
+ else 0
+ )
+ )
+
+ if self.serverVersion() >= MIN_SERVER_VER_DURATION:
+ flds.append(make_field(order.duration))
+
+ if self.serverVersion() >= MIN_SERVER_VER_POST_TO_ATS:
+ flds.append(make_field(order.postToAts))
+
+ if self.serverVersion() >= MIN_SERVER_VER_AUTO_CANCEL_PARENT:
+ flds.append(make_field(order.autoCancelParent))
+
+ if self.serverVersion() >= MIN_SERVER_VER_ADVANCED_ORDER_REJECT:
+ flds.append(make_field(order.advancedErrorOverride))
+
+ if self.serverVersion() >= MIN_SERVER_VER_MANUAL_ORDER_TIME:
+ flds.append(make_field(order.manualOrderTime))
+
+ if self.serverVersion() >= MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS:
+ sendMidOffsets = False
+ if contract.exchange == "IBKRATS":
+ flds.append(make_field_handle_empty(order.minTradeQty))
+ if isPegBestOrder(order.orderType):
+ flds.append(make_field_handle_empty(order.minCompeteSize))
+ flds.append(make_field_handle_empty(order.competeAgainstBestOffset))
+ if (
+ order.competeAgainstBestOffset
+ == COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID
+ ):
+ sendMidOffsets = True
+ elif isPegMidOrder(order.orderType):
+ sendMidOffsets = True
+ if sendMidOffsets:
+ flds.append(make_field_handle_empty(order.midOffsetAtWhole))
+ flds.append(make_field_handle_empty(order.midOffsetAtHalf))
+
+ if self.serverVersion() >= MIN_SERVER_VER_CUSTOMER_ACCOUNT:
+ flds.append(make_field(order.customerAccount))
+
+ if self.serverVersion() >= MIN_SERVER_VER_PROFESSIONAL_CUSTOMER:
+ flds.append(make_field(order.professionalCustomer))
+
+ if self.serverVersion() >= MIN_SERVER_VER_RFQ_FIELDS and self.serverVersion() < MIN_SERVER_VER_UNDO_RFQ_FIELDS:
+ flds.append(make_field(""))
+ flds.append(make_field(UNSET_INTEGER))
+
+ if self.serverVersion() >= MIN_SERVER_VER_INCLUDE_OVERNIGHT:
+ flds.append(make_field(order.includeOvernight))
+
+ if self.serverVersion() >= MIN_SERVER_VER_CME_TAGGING_FIELDS:
+ flds.append(make_field(order.manualOrderIndicator))
+
+ if self.serverVersion() >= MIN_SERVER_VER_IMBALANCE_ONLY:
+ flds.append(make_field(order.imbalanceOnly))
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.PLACE_ORDER, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), FAIL_SEND_ORDER.code(), FAIL_SEND_ORDER.msg() + str(ex))
+ return
+
+ def placeOrderProtoBuf(self, placeOrderRequestProto: PlaceOrderRequestProto):
+ if placeOrderRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ orderId = placeOrderRequestProto.orderId if placeOrderRequestProto.HasField('orderId') else 0
+
+ if not self.isConnected():
+ self.wrapper.error(orderId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if placeOrderRequestProto.HasField('order'):
+ wrongParam = self.validateOrderParameters(placeOrderRequestProto.order)
+ if wrongParam is not None:
+ self.wrapper.error(orderId, currentTimeMillis(),
+ UPDATE_TWS.code(), UPDATE_TWS.msg() + " The following order parameter is not supported by your TWS version - " + wrongParam)
+ return
+
+ if placeOrderRequestProto.HasField('attachedOrders'):
+ wrongParam = self.validateAttachedOrdersParameters(placeOrderRequestProto.attachedOrders)
+ if wrongParam is not None:
+ self.wrapper.error(orderId, currentTimeMillis(),
+ UPDATE_TWS.code(), UPDATE_TWS.msg() + " The following attached orders parameter is not supported by your TWS version - " + wrongParam)
+ return
+
+ try:
+ serializedString = placeOrderRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.PLACE_ORDER + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), FAIL_SEND_ORDER.code(), FAIL_SEND_ORDER.msg() + str(ex))
+ return
+
+ def validateOrderParameters(self, order) -> str | None:
+ if self.serverVersion() < MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_1:
+ if order.HasField('deactivate'):
+ return "deactivate"
+
+ if order.HasField('postOnly'):
+ return "postOnly"
+
+ if order.HasField('allowPreOpen'):
+ return "allowPreOpen"
+
+ if order.HasField('ignoreOpenAuction'):
+ return "ignoreOpenAuction"
+
+ if self.serverVersion() < MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_2:
+ if order.HasField('routeMarketableToBbo'):
+ return "routeMarketableToBbo"
+
+ if order.HasField('seekPriceImprovement'):
+ return "seekPriceImprovement"
+
+ if order.HasField('whatIfType'):
+ return "whatIfType"
+ return None
+
+ def validateAttachedOrdersParameters(self, attachedOrders: AttachedOrdersProto) -> str | None:
+ if self.serverVersion() < MIN_SERVER_VER_ATTACHED_ORDERS:
+ if attachedOrders.HasField('slOrderId'):
+ return "slOrderId"
+ if attachedOrders.HasField('slOrderType'):
+ return "slOrderType"
+ if attachedOrders.HasField('ptOrderId'):
+ return "ptOrderId"
+ if attachedOrders.HasField('ptOrderType'):
+ return "ptOrderType"
+ return None
+
+ def cancelOrder(self, orderId: OrderId, orderCancel: OrderCancel):
+ """Call this function to cancel an order.
+
+ orderId:OrderId - The order ID that was specified previously in the call
+ to placeOrder()"""
+
+ if (self.useProtoBuf(OUT.CANCEL_ORDER)):
+ cancelOrderRequestProto = createCancelOrderRequestProto(orderId, orderCancel)
+ self.cancelOrderProtoBuf(cancelOrderRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_MANUAL_ORDER_TIME
+ and orderCancel.manualOrderCancelTime
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support manual order cancel time attribute",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CME_TAGGING_FIELDS and (
+ orderCancel.extOperator != "" or orderCancel.manualOrderIndicator != UNSET_INTEGER
+ ):
+ self.wrapper.error(
+ orderId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support ext operator and manual order indicator parameters",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ flds = []
+ if self.serverVersion() < MIN_SERVER_VER_CME_TAGGING_FIELDS:
+ flds += [make_field(VERSION)]
+ flds += [make_field(orderId)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_MANUAL_ORDER_TIME:
+ flds += [make_field(orderCancel.manualOrderCancelTime)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_RFQ_FIELDS and self.serverVersion() < MIN_SERVER_VER_UNDO_RFQ_FIELDS:
+ flds += [make_field("")]
+ flds += [make_field("")]
+ flds += [make_field(UNSET_INTEGER)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_CME_TAGGING_FIELDS:
+ flds += [make_field(orderCancel.extOperator)]
+ flds += [make_field(orderCancel.manualOrderIndicator)]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.CANCEL_ORDER, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ def cancelOrderProtoBuf(self, cancelOrderRequestProto: CancelOrderRequestProto):
+ if cancelOrderRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ orderId = cancelOrderRequestProto.orderId if cancelOrderRequestProto.HasField('orderId') else 0
+
+ if not self.isConnected():
+ self.wrapper.error(orderId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelOrderRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_ORDER + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(orderId, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ def reqOpenOrders(self):
+ """Call this function to request the open orders that were
+ placed from this client. Each open order will be fed back through the
+ openOrder() and orderStatus() functions on the EWrapper.
+
+ Note: The client with a clientId of 0 will also receive the TWS-owned
+ open orders. These orders will be associated with the client and a new
+ orderId will be generated. This association will persist over multiple
+ API and TWS sessions."""
+
+ if (self.useProtoBuf(OUT.REQ_OPEN_ORDERS)):
+ openOrdersRequestProto = createOpenOrdersRequestProto()
+ self.reqOpenOrdersProtoBuf(openOrdersRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+
+ self.sendMsg(OUT.REQ_OPEN_ORDERS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqOpenOrdersProtoBuf(self, openOrdersRequestProto: OpenOrdersRequestProto):
+ if openOrdersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = openOrdersRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_OPEN_ORDERS + PROTOBUF_MSG_ID, serializedString)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqAutoOpenOrders(self, bAutoBind: bool):
+ """Call this function to request that newly created TWS orders
+ be implicitly associated with the client. When a new TWS order is
+ created, the order will be associated with the client, and fed back
+ through the openOrder() and orderStatus() functions on the EWrapper.
+
+ Note: This request can only be made from a client with clientId of 0.
+
+ bAutoBind: If set to TRUE, newly created TWS orders will be implicitly
+ associated with the client. If set to FALSE, no association will be
+ made."""
+
+ if (self.useProtoBuf(OUT.REQ_AUTO_OPEN_ORDERS)):
+ autoOpenOrdersRequestProto = createAutoOpenOrdersRequestProto(bAutoBind)
+ self.reqAutoOpenOrdersProtoBuf(autoOpenOrdersRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(bAutoBind)
+ )
+ self.sendMsg(OUT.REQ_AUTO_OPEN_ORDERS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqAutoOpenOrdersProtoBuf(self, autoOpenOrdersRequestProto: AutoOpenOrdersRequestProto):
+ if autoOpenOrdersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = autoOpenOrdersRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_AUTO_OPEN_ORDERS + PROTOBUF_MSG_ID, serializedString)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqAllOpenOrders(self):
+ """Call this function to request the open orders placed from all
+ clients and also from TWS. Each open order will be fed back through the
+ openOrder() and orderStatus() functions on the EWrapper.
+
+ Note: No association is made between the returned orders and the
+ requesting client."""
+
+ if (self.useProtoBuf(OUT.REQ_ALL_OPEN_ORDERS)):
+ allOpenOrdersRequestProto = createAllOpenOrdersRequestProto()
+ self.reqAllOpenOrdersProtoBuf(allOpenOrdersRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+ self.sendMsg(OUT.REQ_ALL_OPEN_ORDERS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqAllOpenOrdersProtoBuf(self, allOpenOrdersRequestProto: AllOpenOrdersRequestProto):
+ if allOpenOrdersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = allOpenOrdersRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_ALL_OPEN_ORDERS + PROTOBUF_MSG_ID, serializedString)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqGlobalCancel(self, orderCancel: OrderCancel):
+ """Use this function to cancel all open orders globally. It
+ cancels both API and TWS open orders.
+
+ If the order was created in TWS, it also gets canceled. If the order
+ was initiated in the API, it also gets canceled."""
+
+ if (self.useProtoBuf(OUT.REQ_GLOBAL_CANCEL)):
+ globalCancelRequestProto = createGlobalCancelRequestProto(orderCancel)
+ self.reqGlobalCancelProtoBuf(globalCancelRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CME_TAGGING_FIELDS and (
+ orderCancel.extOperator != "" or orderCancel.manualOrderIndicator != UNSET_INTEGER
+ ):
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support ext operator and manual order indicator parameters",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ flds = []
+ if self.serverVersion() < MIN_SERVER_VER_CME_TAGGING_FIELDS:
+ flds += [make_field(VERSION)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_CME_TAGGING_FIELDS:
+ flds += [make_field(orderCancel.extOperator)]
+ flds += [make_field(orderCancel.manualOrderIndicator)]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_GLOBAL_CANCEL, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQGLOBALCANCEL.code(), FAIL_SEND_REQGLOBALCANCEL.msg() + str(ex))
+ return
+
+ def reqGlobalCancelProtoBuf(self, globalCancelRequestProto: GlobalCancelRequestProto):
+ if globalCancelRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = globalCancelRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_GLOBAL_CANCEL + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQGLOBALCANCEL.code(), FAIL_SEND_REQGLOBALCANCEL.msg() + str(ex))
+ return
+
+ def reqIds(self, numIds: int):
+ """Call this function to request from TWS the next valid ID that
+ can be used when placing an order. After calling this function, the
+ nextValidId() event will be triggered, and the id returned is that next
+ valid ID. That ID will reflect any autobinding that has occurred (which
+ generates new IDs and increments the next valid ID therein).
+
+ numIds:int - deprecated"""
+
+ if (self.useProtoBuf(OUT.REQ_IDS)):
+ idsRequestProto = createIdsRequestProto(numIds)
+ self.reqIdsProtoBuf(idsRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION) + make_field(numIds)
+ self.sendMsg(OUT.REQ_IDS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ def reqIdsProtoBuf(self, idsRequestProto: IdsRequestProto):
+ if idsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = idsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_IDS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Account and Portfolio
+ ########################################################################
+
+ def reqAccountUpdates(self, subscribe: bool, acctCode: str):
+ """Call this function to start getting account values, portfolio,
+ and last update time information via EWrapper.updateAccountValue(),
+ EWrapperi.updatePortfolio() and Wrapper.updateAccountTime().
+
+ subscribe:bool - If set to TRUE, the client will start receiving account
+ and Portfoliolio updates. If set to FALSE, the client will stop
+ receiving this information.
+ acctCode:str -The account code for which to receive account and
+ portfolio updates."""
+
+ if self.useProtoBuf(OUT.REQ_ACCT_DATA):
+ self.reqAccountUpdatesProtoBuf(createAccountDataRequestProto(subscribe, acctCode))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 2
+
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(subscribe), # TRUE = subscribe, FALSE = unsubscribe.
+ make_field(acctCode),
+ ] # srv v9 and above, the account code. This will only be used for FA clients
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_ACCT_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_ACCT.code(), FAIL_SEND_ACCT.msg() + str(ex))
+ return
+
+ def reqAccountUpdatesProtoBuf(self, accountDataRequestProto: AccountDataRequestProto):
+ if accountDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = accountDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_ACCT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_ACCT.code(), FAIL_SEND_ACCT.msg() + str(ex))
+ return
+
+ def reqAccountSummary(self, reqId: int, groupName: str, tags: str):
+ """Call this method to request and keep up to date the data that appears
+ on the TWS Account Window Summary tab. The data is returned by
+ accountSummary().
+
+ Note: This request is designed for an FA managed account but can be
+ used for any multi-account structure.
+
+ reqId:int - The ID of the data request. Ensures that responses are matched
+ to requests If several requests are in process.
+ groupName:str - Set to All to returnrn account summary data for all
+ accounts, or set to a specific Advisor Account Group name that has
+ already been created in TWS Global Configuration.
+ tags:str - A comma-separated list of account tags. Available tags are:
+ accountountType
+ NetLiquidation,
+ TotalCashValue - Total cash including futures pnl
+ SettledCash - For cash accounts, this is the same as
+ TotalCashValue
+ AccruedCash - Net accrued interest
+ BuyingPower - The maximum amount of marginable US stocks the
+ account can buy
+ EquityWithLoanValue - Cash + stocks + bonds + mutual funds
+ PreviousDayEquityWithLoanValue,
+ GrossPositionValue - The sum of the absolute value of all stock
+ and equity option positions
+ RegTEquity,
+ RegTMargin,
+ SMA - Special Memorandum Account
+ InitMarginReq,
+ MaintMarginReq,
+ AvailableFunds,
+ ExcessLiquidity,
+ Cushion - Excess liquidity as a percentage of net liquidation value
+ FullInitMarginReq,
+ FullMaintMarginReq,
+ FullAvailableFunds,
+ FullExcessLiquidity,
+ LookAheadNextChange - Time when look-ahead values take effect
+ LookAheadInitMarginReq,
+ LookAheadMaintMarginReq,
+ LookAheadAvailableFunds,
+ LookAheadExcessLiquidity,
+ HighestSeverity - A measure of how close the account is to liquidation
+ DayTradesRemaining - The Number of Open/Close trades a user
+ could put on before Pattern Day Trading is detected. A value of "-1"
+ means that the user can put on unlimited day trades.
+ Leverage - GrossPositionValue / NetLiquidation
+ $LEDGER - Single flag to relay all cash balance tags*, only in base
+ currency.
+ $LEDGER:CURRENCY - Single flag to relay all cash balance tags*, only in
+ the specified currency.
+ $LEDGER:ALL - Single flag to relay all cash balance tags* in all
+ currencies."""
+
+ if self.useProtoBuf(OUT.REQ_ACCOUNT_SUMMARY):
+ self.reqAccountSummaryProtoBuf(createAccountSummaryRequestProto(reqId, groupName, tags))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ + make_field(groupName)
+ + make_field(tags)
+ )
+ self.sendMsg(OUT.REQ_ACCOUNT_SUMMARY, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQACCOUNTDATA.code(), FAIL_SEND_REQACCOUNTDATA.msg() + str(ex))
+ return
+
+ def reqAccountSummaryProtoBuf(self, accountSummaryRequestProto: AccountSummaryRequestProto):
+ if accountSummaryRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = accountSummaryRequestProto.reqId if accountSummaryRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = accountSummaryRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_ACCOUNT_SUMMARY + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQACCOUNTDATA.code(), FAIL_SEND_REQACCOUNTDATA.msg() + str(ex))
+ return
+
+ def cancelAccountSummary(self, reqId: int):
+ """Cancels the request for Account Window Summary tab data.
+
+ reqId:int - The ID of the data request being canceled."""
+
+ if self.useProtoBuf(OUT.CANCEL_ACCOUNT_SUMMARY):
+ self.cancelAccountSummaryProtoBuf(createCancelAccountSummaryRequestProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.CANCEL_ACCOUNT_SUMMARY, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANACCOUNTDATA.code(), FAIL_SEND_CANACCOUNTDATA.msg() + str(ex))
+ return
+
+ def cancelAccountSummaryProtoBuf(self, cancelAccountSummaryProto: CancelAccountSummaryProto):
+ if cancelAccountSummaryProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelAccountSummaryProto.reqId if cancelAccountSummaryProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelAccountSummaryProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_ACCOUNT_SUMMARY + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANACCOUNTDATA.code(), FAIL_SEND_CANACCOUNTDATA.msg() + str(ex))
+ return
+
+ def reqPositions(self):
+ """Requests real-time position data for all accounts."""
+
+ if self.useProtoBuf(OUT.REQ_POSITIONS):
+ self.reqPositionsProtoBuf(createPositionsRequestProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_POSITIONS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support positions request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+ self.sendMsg(OUT.REQ_POSITIONS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQPOSITIONS.code(), FAIL_SEND_REQPOSITIONS.msg() + str(ex))
+ return
+
+ def reqPositionsProtoBuf(self, positionsRequestProto: PositionsRequestProto):
+ if positionsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = positionsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_POSITIONS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQPOSITIONS.code(), FAIL_SEND_REQPOSITIONS.msg() + str(ex))
+ return
+
+ def cancelPositions(self):
+ """Cancels real-time position updates."""
+
+ if self.useProtoBuf(OUT.CANCEL_POSITIONS):
+ self.cancelPositionsProtoBuf(createCancelPositionsRequestProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_POSITIONS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support positions request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+
+ self.sendMsg(OUT.CANCEL_POSITIONS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CANPOSITIONS.code(), FAIL_SEND_CANPOSITIONS.msg() + str(ex))
+ return
+
+ def cancelPositionsProtoBuf(self, cancelPositionsProto: CancelPositionsProto):
+ if cancelPositionsProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelPositionsProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_POSITIONS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CANPOSITIONS.code(), FAIL_SEND_CANPOSITIONS.msg() + str(ex))
+ return
+
+ def reqPositionsMulti(self, reqId: int, account: str, modelCode: str):
+ """Requests positions for account and/or model.
+ Results are delivered via EWrapper.positionMulti() and
+ EWrapper.positionMultiEnd()"""
+
+ if self.useProtoBuf(OUT.REQ_POSITIONS_MULTI):
+ self.reqPositionsMultiProtoBuf(createPositionsMultiRequestProto(reqId, account, modelCode))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MODELS_SUPPORT:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support positions multi request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ + make_field(account)
+ + make_field(modelCode)
+ )
+ self.sendMsg(OUT.REQ_POSITIONS_MULTI, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQPOSITIONSMULTI.code(), FAIL_SEND_REQPOSITIONSMULTI.msg() + str(ex))
+ return
+
+ def reqPositionsMultiProtoBuf(self, positionsMultiRequestProto: PositionsMultiRequestProto):
+ if positionsMultiRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = positionsMultiRequestProto.reqId if positionsMultiRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = positionsMultiRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_POSITIONS_MULTI + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQPOSITIONSMULTI.code(), FAIL_SEND_REQPOSITIONSMULTI.msg() + str(ex))
+ return
+
+ def cancelPositionsMulti(self, reqId: int):
+ if self.useProtoBuf(OUT.CANCEL_POSITIONS_MULTI):
+ self.cancelPositionsMultiProtoBuf(createCancelPositionsMultiRequestProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MODELS_SUPPORT:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support cancel positions multi request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.CANCEL_POSITIONS_MULTI, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANPOSITIONSMULTI.code(), FAIL_SEND_CANPOSITIONSMULTI.msg() + str(ex))
+ return
+
+ def cancelPositionsMultiProtoBuf(self, cancelPositionsMultiProto: CancelPositionsMultiProto):
+ if cancelPositionsMultiProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelPositionsMultiProto.reqId if cancelPositionsMultiProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelPositionsMultiProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_POSITIONS_MULTI + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANPOSITIONSMULTI.code(), FAIL_SEND_CANPOSITIONSMULTI.msg() + str(ex))
+ return
+
+ def reqAccountUpdatesMulti(
+ self, reqId: int, account: str, modelCode: str, ledgerAndNLV: bool
+ ):
+ """Requests account updates for account and/or model."""
+
+ if self.useProtoBuf(OUT.REQ_ACCOUNT_UPDATES_MULTI):
+ self.reqAccountUpdatesMultiProtoBuf(createAccountUpdatesMultiRequestProto(reqId, account, modelCode, ledgerAndNLV))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MODELS_SUPPORT:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support account updates multi request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ + make_field(account)
+ + make_field(modelCode)
+ + make_field(ledgerAndNLV)
+ )
+ self.sendMsg(OUT.REQ_ACCOUNT_UPDATES_MULTI, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQACCOUNTUPDATESMULTI.code(), FAIL_SEND_REQACCOUNTUPDATESMULTI.msg() + str(ex))
+ return
+
+ def reqAccountUpdatesMultiProtoBuf(self, accountUpdatesMultiRequestProto: AccountUpdatesMultiRequestProto):
+ if accountUpdatesMultiRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = accountUpdatesMultiRequestProto.reqId if accountUpdatesMultiRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = accountUpdatesMultiRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_ACCOUNT_UPDATES_MULTI + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQACCOUNTUPDATESMULTI.code(), FAIL_SEND_REQACCOUNTUPDATESMULTI.msg() + str(ex))
+ return
+
+ def cancelAccountUpdatesMulti(self, reqId: int):
+
+ if self.useProtoBuf(OUT.CANCEL_ACCOUNT_UPDATES_MULTI):
+ self.cancelAccountUpdatesMultiProtoBuf(createCancelAccountUpdatesMultiRequestProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_MODELS_SUPPORT:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support cancel account updates multi request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.CANCEL_ACCOUNT_UPDATES_MULTI, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANACCOUNTUPDATESMULTI.code(), FAIL_SEND_CANACCOUNTUPDATESMULTI.msg() + str(ex))
+ return
+
+ def cancelAccountUpdatesMultiProtoBuf(self, cancelAccountUpdatesMultiProto: CancelAccountUpdatesMultiProto):
+ if cancelAccountUpdatesMultiProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelAccountUpdatesMultiProto.reqId if cancelAccountUpdatesMultiProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelAccountUpdatesMultiProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_ACCOUNT_UPDATES_MULTI + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANACCOUNTUPDATESMULTI.code(), FAIL_SEND_CANACCOUNTUPDATESMULTI.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Daily PnL
+ #########################################################################
+
+ def reqPnL(self, reqId: int, account: str, modelCode: str):
+ if self.useProtoBuf(OUT.REQ_PNL):
+ self.reqPnLProtoBuf(createPnLRequestProto(reqId, account, modelCode))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_PNL:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support PnL request.",
+ )
+ return
+
+ try:
+ msg = (
+ make_field(reqId)
+ + make_field(account)
+ + make_field(modelCode)
+ )
+ self.sendMsg(OUT.REQ_PNL, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQPNL.code(), FAIL_SEND_REQPNL.msg() + str(ex))
+ return
+
+ def reqPnLProtoBuf(self, pnlRequestProto: PnLRequestProto):
+ if pnlRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = pnlRequestProto.reqId if pnlRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = pnlRequestProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.REQ_PNL + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQPNL.code(), FAIL_SEND_REQPNL.msg() + str(ex))
+ return
+
+ def cancelPnL(self, reqId: int):
+ if self.useProtoBuf(OUT.CANCEL_PNL):
+ self.cancelPnLProtoBuf(createCancelPnLProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_PNL:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support PnL request.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+
+ self.sendMsg(OUT.CANCEL_PNL, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELPNL.code(), FAIL_SEND_CANCELPNL.msg() + str(ex))
+ return
+
+ def cancelPnLProtoBuf(self, cancelPnLProto: CancelPnLProto):
+ if cancelPnLProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelPnLProto.reqId if cancelPnLProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelPnLProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.CANCEL_PNL + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELPNL.code(), FAIL_SEND_CANCELPNL.msg() + str(ex))
+ return
+
+ def reqPnLSingle(self, reqId: int, account: str, modelCode: str, conid: int):
+ if self.useProtoBuf(OUT.REQ_PNL_SINGLE):
+ self.reqPnLSingleProtoBuf(createPnLSingleRequestProto(reqId, account, modelCode, conid))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_PNL:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support PnL request.",
+ )
+ return
+
+ try:
+ msg = (
+ make_field(reqId)
+ + make_field(account)
+ + make_field(modelCode)
+ + make_field(conid)
+ )
+ self.sendMsg(OUT.REQ_PNL_SINGLE, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQPNLSINGLE.code(), FAIL_SEND_REQPNLSINGLE.msg() + str(ex))
+ return
+
+ def reqPnLSingleProtoBuf(self, pnlSingleRequestProto: PnLSingleRequestProto):
+ if pnlSingleRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = pnlSingleRequestProto.reqId if pnlSingleRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = pnlSingleRequestProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.REQ_PNL_SINGLE + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQPNLSINGLE.code(), FAIL_SEND_REQPNLSINGLE.msg() + str(ex))
+ return
+
+ def cancelPnLSingle(self, reqId: int):
+ if self.useProtoBuf(OUT.CANCEL_PNL_SINGLE):
+ self.cancelPnLSingleProtoBuf(createCancelPnLSingleProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_PNL:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support PnL request.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.CANCEL_PNL_SINGLE, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELPNLSINGLE.code(), FAIL_SEND_CANCELPNLSINGLE.msg() + str(ex))
+ return
+
+ def cancelPnLSingleProtoBuf(self, cancelPnLSingleProto: CancelPnLSingleProto):
+ if cancelPnLSingleProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelPnLSingleProto.reqId if cancelPnLSingleProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelPnLSingleProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.CANCEL_PNL_SINGLE + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELPNLSINGLE.code(), FAIL_SEND_CANCELPNLSINGLE.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Executions
+ #########################################################################
+
+ def reqExecutions(self, reqId: int, execFilter: ExecutionFilter):
+ """When this function is called, the execution reports that meet the
+ filter criteria are downloaded to the client via the execDetails()
+ function. To view executions beyond the past 24 hours, open the
+ Trade Log in TWS and, while the Trade Log is displayed, request
+ the executions again from the API.
+
+ reqId:int - The ID of the data request. Ensures that responses are
+ matched to requests if several requests are in process.
+ execFilter:ExecutionFilter - This object contains attributes that
+ describe the filter criteria used to determine which execution
+ reports are returned.
+
+ NOTE: Time format must be 'yyyymmdd-hh:mm:ss' Eg: '20030702-14:55'"""
+ if (self.useProtoBuf(OUT.REQ_EXECUTIONS)):
+ executionRequestProto = createExecutionRequestProto(reqId, execFilter)
+ self.reqExecutionsProtoBuf(executionRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+
+ if self.serverVersion() < MIN_SERVER_VER_PARAMETRIZED_DAYS_OF_EXECUTIONS:
+ if (
+ execFilter.lastNDays != UNSET_INTEGER
+ or execFilter.specificDates is not None
+ ):
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support last N days and specific dates parameters",
+ )
+ return
+
+ try:
+ VERSION = 3
+
+ # send req open orders msg
+ flds = []
+ flds += [make_field(VERSION)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_EXECUTION_DATA_CHAIN:
+ flds += [
+ make_field(reqId),
+ ]
+
+ # Send the execution rpt filter data (srv v9 and above)
+ flds += [
+ make_field(execFilter.clientId),
+ make_field(execFilter.acctCode),
+ make_field(execFilter.time),
+ make_field(execFilter.symbol),
+ make_field(execFilter.secType),
+ make_field(execFilter.exchange),
+ make_field(execFilter.side),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_PARAMETRIZED_DAYS_OF_EXECUTIONS:
+ flds += [
+ make_field(execFilter.lastNDays),
+ ]
+ if execFilter.specificDates is not None :
+ flds += [
+ make_field(len(execFilter.specificDates)),
+ ]
+ for specificDate in execFilter.specificDates:
+ flds += [
+ make_field(specificDate),
+ ]
+ else:
+ flds += [
+ make_field(0),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_EXECUTIONS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_EXEC.code(), FAIL_SEND_EXEC.msg() + str(ex))
+ return
+
+ def reqExecutionsProtoBuf(self, executionRequestProto: ExecutionRequestProto):
+ if executionRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = executionRequestProto.reqId if executionRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = executionRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_EXECUTIONS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_EXEC.code(), FAIL_SEND_EXEC.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Contract Details
+ #########################################################################
+
+ def reqContractDetails(self, reqId: int, contract: Contract):
+ """Call this function to download all details for a particular
+ underlying. The contract details will be received via the contractDetails()
+ function on the EWrapper.
+
+ reqId:int - The ID of the data request. Ensures that responses are
+ make_fieldatched to requests if several requests are in process.
+ contract:Contract - The summary description of the contract being looked
+ up."""
+
+ if (self.useProtoBuf(OUT.REQ_CONTRACT_DATA)):
+ contractDataRequestProto = createContractDataRequestProto(reqId, contract)
+ self.reqContractDataProtoBuf(contractDataRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SEC_ID_TYPE:
+ if contract.secIdType or contract.secId:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support secIdType and secId parameters.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support tradingClass parameter in reqContractDetails.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ if contract.primaryExchange:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support primaryExchange parameter in reqContractDetails.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_BOND_ISSUERID:
+ if contract.issuerId:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support issuerId parameter in reqContractDetails.",
+ )
+ return
+
+ try:
+ VERSION = 8
+
+ # send req mkt data msg
+ flds = []
+ flds += [make_field(VERSION)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_CONTRACT_DATA_CHAIN:
+ flds += [
+ make_field(reqId),
+ ]
+
+ # send contract fields
+ flds += [
+ make_field(contract.conId), # srv v37 and above
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ ] # srv v15 and above
+
+ if self.serverVersion() >= MIN_SERVER_VER_PRIMARYEXCH:
+ flds += [
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ ]
+ elif self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ if contract.primaryExchange and (
+ contract.exchange == "BEST" or contract.exchange == "SMART"
+ ):
+ flds += [
+ make_field(contract.exchange + ":" + contract.primaryExchange),
+ ]
+ else:
+ flds += [
+ make_field(contract.exchange),
+ ]
+
+ flds += [make_field(contract.currency), make_field(contract.localSymbol)]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+ flds += [
+ make_field(contract.includeExpired),
+ ] # srv v31 and above
+
+ if self.serverVersion() >= MIN_SERVER_VER_SEC_ID_TYPE:
+ flds += [make_field(contract.secIdType), make_field(contract.secId)]
+
+ if self.serverVersion() >= MIN_SERVER_VER_BOND_ISSUERID:
+ flds += [
+ make_field(contract.issuerId),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_CONTRACT_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCONTRACT.code(), FAIL_SEND_REQCONTRACT.msg() + str(ex))
+ return
+
+ def reqContractDataProtoBuf(self, contractDataRequestProto: ContractDataRequestProto):
+ if contractDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = contractDataRequestProto.reqId if contractDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = contractDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_CONTRACT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCONTRACT.code(), FAIL_SEND_REQCONTRACT.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Market Depth
+ #########################################################################
+
+ def reqMktDepthExchanges(self):
+ if (self.useProtoBuf(OUT.REQ_MKT_DEPTH_EXCHANGES)):
+ marketDepthExchangesRequestProto = createMarketDepthExchangesRequestProto()
+ self.reqMarketDepthExchangesProtoBuf(marketDepthExchangesRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_MKT_DEPTH_EXCHANGES:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support market depth exchanges request.",
+ )
+ return
+
+ try:
+ self.sendMsg(OUT.REQ_MKT_DEPTH_EXCHANGES, "")
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQMKTDEPTHEXCHANGES.code(), FAIL_SEND_REQMKTDEPTHEXCHANGES.msg() + str(ex))
+ return
+
+ def reqMarketDepthExchangesProtoBuf(self, marketDepthExchangesRequestProto: MarketDepthExchangesRequestProto):
+ if marketDepthExchangesRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = marketDepthExchangesRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MKT_DEPTH_EXCHANGES + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQMKTDEPTHEXCHANGES.code(), FAIL_SEND_REQMKTDEPTHEXCHANGES.msg() + str(ex))
+ return
+
+ def reqMktDepth(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ numRows: int,
+ isSmartDepth: bool,
+ mktDepthOptions: TagValueList,
+ ):
+ """Call this function to request market depth for a specific
+ contract. The market depth will be returned by the updateMktDepth() and
+ updateMktDepthL2() events.
+
+ Requests the contract's market depth (order book). Note this request must be
+ direct-routed to an exchange and not smart-routed. The number of simultaneous
+ market depth requests allowed in an account is calculated based on a formula
+ that looks at an accounts' equity, commission and fees, and quote booster packs.
+
+ reqId:TickerId - The ticker id. Must be a unique value. When the market
+ depth data returns, it will be identified by this tag. This is
+ also used when canceling the market depth
+ contract:Contact - This structure contains a description of the contract
+ for which market depth data is being requested.
+ numRows:int - Specifies the numRowsumber of market depth rows to display.
+ isSmartDepth:bool - specifies SMART depth request
+ mktDepthOptions:TagValueList - For internal use only. Use default value
+ XYZ."""
+
+ if (self.useProtoBuf(OUT.REQ_MKT_DEPTH)):
+ marketDepthRequestProto = createMarketDepthRequestProto(reqId, contract, numRows, isSmartDepth, mktDepthOptions)
+ self.reqMarketDepthProtoBuf(marketDepthRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass or contract.conId > 0:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support conId and tradingClass parameters in reqMktDepth.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SMART_DEPTH and isSmartDepth:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support SMART depth request.",
+ )
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_MKT_DEPTH_PRIM_EXCHANGE
+ and contract.primaryExchange
+ ):
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support primaryExchange parameter in reqMktDepth.",
+ )
+ return
+
+ try:
+ VERSION = 5
+
+ # send req mkt depth msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.conId),
+ ]
+ flds += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier), # srv v15 and above
+ make_field(contract.exchange),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_MKT_DEPTH_PRIM_EXCHANGE:
+ flds += [
+ make_field(contract.primaryExchange),
+ ]
+ flds += [make_field(contract.currency), make_field(contract.localSymbol)]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+
+ flds += [
+ make_field(numRows),
+ ] # srv v19 and above
+
+ if self.serverVersion() >= MIN_SERVER_VER_SMART_DEPTH:
+ flds += [
+ make_field(isSmartDepth),
+ ]
+
+ # send mktDepthOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ # current doc says this part if for "internal use only" -> won't support it
+ if mktDepthOptions:
+ raise NotImplementedError("not supported")
+ mktDataOptionsStr = ""
+ flds += [
+ make_field(mktDataOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_MKT_DEPTH, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMKTDEPTH.code(), FAIL_SEND_REQMKTDEPTH.msg() + str(ex))
+ return
+
+ def reqMarketDepthProtoBuf(self, marketDepthRequestProto: MarketDepthRequestProto):
+ if marketDepthRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = marketDepthRequestProto.reqId if marketDepthRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = marketDepthRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MKT_DEPTH + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMKTDEPTH.code(), FAIL_SEND_REQMKTDEPTH.msg() + str(ex))
+ return
+
+ def cancelMktDepth(self, reqId: TickerId, isSmartDepth: bool):
+ """After calling this function, market depth data for the specified id
+ will stop flowing.
+
+ reqId:TickerId - The ID that was specified in the call to
+ reqMktDepth().
+ isSmartDepth:bool - specifies SMART depth request"""
+
+ if (self.useProtoBuf(OUT.CANCEL_MKT_DEPTH)):
+ cancelMarketDepthProto = createCancelMarketDepthProto(reqId, isSmartDepth)
+ self.cancelMarketDepthProtoBuf(cancelMarketDepthProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SMART_DEPTH and isSmartDepth:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support SMART depth cancel.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ # send cancel mkt depth msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_SMART_DEPTH:
+ flds += [make_field(isSmartDepth)]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.CANCEL_MKT_DEPTH, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANMKTDEPTH.code(), FAIL_SEND_CANMKTDEPTH.msg() + str(ex))
+ return
+
+ def cancelMarketDepthProtoBuf(self, cancelMarketDepthProto: CancelMarketDepthProto):
+ if cancelMarketDepthProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelMarketDepthProto.reqId if cancelMarketDepthProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelMarketDepthProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_MKT_DEPTH + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANMKTDEPTH.code(), FAIL_SEND_CANMKTDEPTH.msg() + str(ex))
+ return
+
+ #########################################################################
+ # News Bulletins
+ #########################################################################
+
+ def reqNewsBulletins(self, allMsgs: bool):
+ """Call this function to start receiving news bulletins. Each bulletin
+ will be returned by the updateNewsBulletin() event.
+
+ allMsgs:bool - If set to TRUE, returns all the existing bulletins for
+ the currencyent day and any new ones. If set to FALSE, will only
+ return new bulletins."""
+
+ if self.useProtoBuf(OUT.REQ_NEWS_BULLETINS):
+ self.reqNewsBulletinsProtoBuf(createNewsBulletinsRequestProto(allMsgs))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(allMsgs)
+ )
+
+ self.sendMsg(OUT.REQ_NEWS_BULLETINS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ def reqNewsBulletinsProtoBuf(self, newsBulletinsRequestProto: NewsBulletinsRequestProto):
+ if newsBulletinsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = newsBulletinsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_NEWS_BULLETINS + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ def cancelNewsBulletins(self):
+ """Call this function to stop receiving news bulletins."""
+
+ if self.useProtoBuf(OUT.CANCEL_NEWS_BULLETINS):
+ self.cancelNewsBulletinsProtoBuf(createCancelNewsBulletinsProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+ self.sendMsg(OUT.CANCEL_NEWS_BULLETINS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ def cancelNewsBulletinsProtoBuf(self, cancelNewsBulletinsProto: CancelNewsBulletinsProto):
+ if cancelNewsBulletinsProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelNewsBulletinsProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_NEWS_BULLETINS + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CORDER.code(), FAIL_SEND_CORDER.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Financial Advisors
+ #########################################################################
+
+ def reqManagedAccts(self):
+ """Call this function to request the list of managed accounts. The list
+ will be returned by the managedAccounts() function on the EWrapper.
+
+ Note: This request can only be made when connected to a FA managed account."""
+
+ if self.useProtoBuf(OUT.REQ_MANAGED_ACCTS):
+ self.reqManagedAcctsProtoBuf(createManagedAccountsRequestProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+ return self.sendMsg(OUT.REQ_MANAGED_ACCTS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_OORDER.code(), FAIL_SEND_OORDER.msg() + str(ex))
+ return
+
+ def reqManagedAcctsProtoBuf(self, managedAccountsRequestProto: ManagedAccountsRequestProto):
+ if managedAccountsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = managedAccountsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MANAGED_ACCTS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_ACCT.code(), FAIL_SEND_ACCT.msg() + str(ex))
+ return
+
+ def requestFA(self, faData: FaDataType):
+ """Call this function to request FA configuration information from TWS.
+ The data returns in an XML string via a "receiveFA" ActiveX event.
+
+ faData:FaDataType - Specifies the type of Financial Advisor
+ configuration data beingingg requested. Valid values include:
+ 1 = GROUPS
+ 3 = ACCOUNT ALIASES"""
+
+ if (self.useProtoBuf(OUT.REQ_FA)):
+ faRequestProto = createFARequestProto(int(faData))
+ self.reqFAProtoBuf(faRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() >= MIN_SERVER_VER_FA_PROFILE_DESUPPORT and faData == 2:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ FA_PROFILE_NOT_SUPPORTED.code(),
+ FA_PROFILE_NOT_SUPPORTED.msg(),
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION) + make_field(int(faData))
+ return self.sendMsg(OUT.REQ_FA, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_FA_REQUEST.code(), FAIL_SEND_FA_REQUEST.msg() + str(ex))
+ return
+
+ def reqFAProtoBuf(self, faRequestProto: FARequestProto):
+ if faRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = faRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_FA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_FA_REQUEST.code(), FAIL_SEND_FA_REQUEST.msg() + str(ex))
+ return
+
+ def replaceFA(self, reqId: TickerId, faData: FaDataType, cxml: str):
+ """Call this function to modify FA configuration information from the
+ API. Note that this can also be done manually in TWS itself.
+
+ reqId:TickerId - request id
+ faData:FaDataType - Specifies the type of Financial Advisor
+ configuration data beingingg requested. Valid values include:
+ 1 = GROUPS
+ 3 = ACCOUNT ALIASES
+ cxml: str - The XML string containing the new FA configuration
+ information."""
+
+ if (self.useProtoBuf(OUT.REPLACE_FA)):
+ faReplaceProto = createFAReplaceProto(reqId, int(faData), cxml)
+ self.replaceFAProtoBuf(faReplaceProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() >= MIN_SERVER_VER_FA_PROFILE_DESUPPORT and faData == 2:
+ self.wrapper.error(reqId, currentTimeMillis(), FA_PROFILE_NOT_SUPPORTED.code(), FA_PROFILE_NOT_SUPPORTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(int(faData))
+ + make_field(cxml)
+ )
+
+ if self.serverVersion() >= MIN_SERVER_VER_REPLACE_FA_END:
+ msg += make_field(reqId)
+ return self.sendMsg(OUT.REPLACE_FA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_FA_REPLACE.code(), FAIL_SEND_FA_REPLACE.msg() + str(ex))
+ return
+
+ def replaceFAProtoBuf(self, faReplaceProto: FAReplaceProto):
+ if faReplaceProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = faReplaceProto.reqId if faReplaceProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = faReplaceProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REPLACE_FA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_FA_REPLACE.code(), FAIL_SEND_FA_REPLACE.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Historical Data
+ #########################################################################
+
+ def reqHistoricalData(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ endDateTime: str,
+ durationStr: str,
+ barSizeSetting: str,
+ whatToShow: str,
+ useRTH: int,
+ formatDate: int,
+ keepUpToDate: bool,
+ chartOptions: TagValueList,
+ ):
+ """Requests contracts' historical data. When requesting historical data, a
+ finishing time and date is required along with a duration string. The
+ resulting bars will be returned in EWrapper.historicalData()
+
+ reqId:TickerId - The id of the request. Must be a unique value. When the
+ market data returns, it whatToShowill be identified by this tag. This is also
+ used when canceling the market data.
+ contract:Contract - This object contains a description of the contract for which
+ market data is being requested.
+ endDateTime:str - Defines a query end date and time at any point during the past 6 mos.
+ Valid values include any date/time within the past six months in the format:
+ yyyymmdd HH:mm:ss ttt
+
+ where "ttt" is the optional time zone.
+ durationStr:str - Set the query duration up to one week, using a time unit
+ of seconds, days or weeks. Valid values include any integer followed by a space
+ and then S (seconds), D (days) or W (week). If no unit is specified, seconds is used.
+ barSizeSetting:str - Specifies the size of the bars that will be returned (within IB/TWS listimits).
+ Valid values include:
+ 1 sec
+ 5 secs
+ 15 secs
+ 30 secs
+ 1 min
+ 2 mins
+ 3 mins
+ 4 mins
+ 5 mins
+ 15 mins
+ 30 mins
+ 1 hour
+ 1 day
+ whatToShow:str - Determines the nature of data beinging extracted. Valid values include:
+
+ TRADES
+ MIDPOINT
+ BID
+ ASK
+ BID_ASK
+ HISTORICAL_VOLATILITY
+ OPTION_IMPLIED_VOLATILITY
+ SCHEDULE
+ useRTH:int - Determines whether to return all data available during the requested time span,
+ or only data that falls within regular trading hours. Valid values include:
+
+ 0 - all data is returned even where the market in question was outside its
+ regular trading hours.
+ 1 - only data within the regular trading hours is returned, even if the
+ requested time span falls partially or completely outside the RTH.
+ formatDate: int - Determines the date format applied to returned bars. validd values include:
+
+ 1 - dates applying to bars returned in the format: yyyymmdd{space}{space}hh:mm:dd
+ 2 - dates are returned as a long integer specifying the number of seconds since
+ 1/1/1970 GMT.
+ chartOptions:TagValueList - For internal use only. Use default value XYZ."""
+
+ if self.useProtoBuf(OUT.REQ_HISTORICAL_DATA):
+ historicalDataRequestProto = createHistoricalDataRequestProto(reqId, contract, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH != 0, formatDate, keepUpToDate, chartOptions)
+ self.reqHistoricalDataProtoBuf(historicalDataRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass or contract.conId > 0:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support conId and tradingClass parameters in reqHistoricalData.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_HISTORICAL_SCHEDULE:
+ if whatToShow == "SCHEDULE":
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support requesting of historical schedule.",
+ )
+ return
+
+ try:
+ VERSION = 6
+
+ # send req mkt data msg
+ flds = []
+
+ if self.serverVersion() < MIN_SERVER_VER_SYNT_REALTIME_BARS:
+ flds += [
+ make_field(VERSION),
+ ]
+
+ flds += [
+ make_field(reqId),
+ ]
+
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.conId),
+ ]
+ flds += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+ flds += [
+ make_field(contract.includeExpired), # srv v31 and above
+ make_field(endDateTime), # srv v20 and above
+ make_field(barSizeSetting), # srv v20 and above
+ make_field(durationStr),
+ make_field(useRTH),
+ make_field(whatToShow),
+ make_field(formatDate),
+ ] # srv v16 and above
+
+ # Send combo legs for BAG requests
+ if contract.secType == "BAG":
+ flds += [
+ make_field(len(contract.comboLegs)),
+ ]
+ for comboLeg in contract.comboLegs:
+ flds += [
+ make_field(comboLeg.conId),
+ make_field(comboLeg.ratio),
+ make_field(comboLeg.action),
+ make_field(comboLeg.exchange),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_SYNT_REALTIME_BARS:
+ flds += [
+ make_field(keepUpToDate),
+ ]
+
+ # send chartOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ chartOptionsStr = ""
+ if chartOptions:
+ for tagValue in chartOptions:
+ chartOptionsStr += str(tagValue)
+ flds += [
+ make_field(chartOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_HISTORICAL_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQHISTDATA.code(), FAIL_SEND_REQHISTDATA.msg() + str(ex))
+ return
+
+ def reqHistoricalDataProtoBuf(self, historicalDataRequestProto: HistoricalDataRequestProto):
+ if historicalDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = historicalDataRequestProto.reqId if historicalDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = historicalDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_HISTORICAL_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHISTDATA.code(), FAIL_SEND_REQHISTDATA.msg() + str(ex))
+ return
+
+ def cancelHistoricalData(self, reqId: TickerId):
+ """Used if an internet disconnect has occurred or the results of a query
+ are otherwise delayed and the application is no longer interested in receiving
+ the data.
+
+ reqId:TickerId - The ticker ID. Must be a unique value."""
+
+ if self.useProtoBuf(OUT.CANCEL_HISTORICAL_DATA):
+ cancelHistoricalDataProto = createCancelHistoricalDataProto(reqId)
+ self.cancelHistoricalDataProtoBuf(cancelHistoricalDataProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.CANCEL_HISTORICAL_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANHISTDATA.code(), FAIL_SEND_CANHISTDATA.msg() + str(ex))
+ return
+
+ def cancelHistoricalDataProtoBuf(self, cancelHistoricalDataProto: CancelHistoricalDataProto):
+ if cancelHistoricalDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelHistoricalDataProto.reqId if cancelHistoricalDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelHistoricalDataProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_HISTORICAL_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANHISTDATA.code(), FAIL_SEND_CANHISTDATA.msg() + str(ex))
+ return
+
+ # Note that formatData parameter affects intraday bars only
+ # 1-day bars always return with date in YYYYMMDD format
+
+ def reqHeadTimeStamp(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ whatToShow: str,
+ useRTH: int,
+ formatDate: int,
+ ):
+ if self.useProtoBuf(OUT.REQ_HEAD_TIMESTAMP):
+ headTimestampRequestProto = createHeadTimestampRequestProto(reqId, contract, whatToShow, useRTH != 0, formatDate)
+ self.reqHeadTimestampProtoBuf(headTimestampRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_HEAD_TIMESTAMP:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support head time stamp requests.",
+ )
+ return
+
+ try:
+ flds = []
+ flds += [
+ make_field(reqId),
+ make_field(contract.conId),
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ make_field(contract.tradingClass),
+ make_field(contract.includeExpired),
+ make_field(useRTH),
+ make_field(whatToShow),
+ make_field(formatDate),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_HEAD_TIMESTAMP, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHEADTIMESTAMP.code(), FAIL_SEND_REQHEADTIMESTAMP.msg() + str(ex))
+ return
+
+ def reqHeadTimestampProtoBuf(self, headTimestampRequestProto: HeadTimestampRequestProto):
+ if headTimestampRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = headTimestampRequestProto.reqId if headTimestampRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = headTimestampRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_HEAD_TIMESTAMP + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHEADTIMESTAMP.code(), FAIL_SEND_REQHEADTIMESTAMP.msg() + str(ex))
+ return
+
+ def cancelHeadTimeStamp(self, reqId: TickerId):
+ if self.useProtoBuf(OUT.CANCEL_HEAD_TIMESTAMP):
+ cancelHeadTimestampProto = createCancelHeadTimestampProto(reqId)
+ self.cancelHeadTimestampProtoBuf(cancelHeadTimestampProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CANCEL_HEADTIMESTAMP:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support head time stamp requests.",
+ )
+ return
+
+ flds = []
+ try:
+ flds += [make_field(reqId)]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.CANCEL_HEAD_TIMESTAMP, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_CANCELHEADTIMESTAMP.code(), FAIL_SEND_CANCELHEADTIMESTAMP.msg() + str(ex))
+ return
+
+ def cancelHeadTimestampProtoBuf(self, cancelHeadTimestampProto: CancelHeadTimestampProto):
+ if cancelHeadTimestampProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelHeadTimestampProto.reqId if cancelHeadTimestampProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelHeadTimestampProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_HEAD_TIMESTAMP + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELHEADTIMESTAMP.code(), FAIL_SEND_CANCELHEADTIMESTAMP.msg() + str(ex))
+ return
+
+ def reqHistogramData(
+ self, tickerId: int, contract: Contract, useRTH: bool, timePeriod: str
+ ):
+ if self.useProtoBuf(OUT.REQ_HISTOGRAM_DATA):
+ histogramDataRequestProto = createHistogramDataRequestProto(tickerId, contract, useRTH, timePeriod)
+ self.reqHistogramDataProtoBuf(histogramDataRequestProto )
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_HISTOGRAM:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support histogram requests..",
+ )
+ return
+
+ try:
+ flds = []
+ flds += [
+ make_field(tickerId),
+ make_field(contract.conId),
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ make_field(contract.tradingClass),
+ make_field(contract.includeExpired),
+ make_field(useRTH),
+ make_field(timePeriod),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_HISTOGRAM_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(tickerId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(tickerId, currentTimeMillis(), FAIL_SEND_REQHISTOGRAMDATA.code(), FAIL_SEND_REQHISTOGRAMDATA.msg() + str(ex))
+ return
+
+ def reqHistogramDataProtoBuf(self, histogramDataRequestProto: HistogramDataRequestProto):
+ if histogramDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = histogramDataRequestProto.reqId if histogramDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = histogramDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_HISTOGRAM_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHISTOGRAMDATA.code(), FAIL_SEND_REQHISTOGRAMDATA.msg() + str(ex))
+ return
+
+ def cancelHistogramData(self, tickerId: int):
+ if self.useProtoBuf(OUT.CANCEL_HISTOGRAM_DATA):
+ cancelHistogramDataProto = createCancelHistogramDataProto(tickerId)
+ self.cancelHistogramDataProtoBuf(cancelHistogramDataProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_HISTOGRAM:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support histogram requests..",
+ )
+ return
+
+ msg = make_field(tickerId)
+
+ try:
+ self.sendMsg(OUT.CANCEL_HISTOGRAM_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(tickerId, currentTimeMillis(), FAIL_SEND_CANCELHISTOGRAMDATA.code(), FAIL_SEND_CANCELHISTOGRAMDATA.msg() + str(ex))
+ return
+
+ def cancelHistogramDataProtoBuf(self, cancelHistogramDataProto: CancelHistogramDataProto):
+ if cancelHistogramDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelHistogramDataProto.reqId if cancelHistogramDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelHistogramDataProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_HISTOGRAM_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCELHISTOGRAMDATA.code(), FAIL_SEND_CANCELHISTOGRAMDATA.msg() + str(ex))
+ return
+
+ def reqHistoricalTicks(
+ self,
+ reqId: int,
+ contract: Contract,
+ startDateTime: str,
+ endDateTime: str,
+ numberOfTicks: int,
+ whatToShow: str,
+ useRth: int,
+ ignoreSize: bool,
+ miscOptions: TagValueList,
+ ):
+ if self.useProtoBuf(OUT.REQ_HISTORICAL_TICKS):
+ historicalTicksRequestProto = createHistoricalTicksRequestProto(reqId, contract, startDateTime, endDateTime, numberOfTicks, whatToShow, useRth != 0, ignoreSize, miscOptions)
+ self.reqHistoricalTicksProtoBuf(historicalTicksRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_HISTORICAL_TICKS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support historical ticks requests..",
+ )
+ return
+
+ try:
+ flds = []
+ flds += [
+ make_field(reqId),
+ make_field(contract.conId),
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ make_field(contract.tradingClass),
+ make_field(contract.includeExpired),
+ make_field(startDateTime),
+ make_field(endDateTime),
+ make_field(numberOfTicks),
+ make_field(whatToShow),
+ make_field(useRth),
+ make_field(ignoreSize),
+ ]
+
+ miscOptionsString = ""
+ if miscOptions:
+ for tagValue in miscOptions:
+ miscOptionsString += str(tagValue)
+ flds += [
+ make_field(miscOptionsString),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_HISTORICAL_TICKS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHISTORICALTICKS.code(), FAIL_SEND_REQHISTORICALTICKS.msg() + str(ex))
+ return
+
+ def reqHistoricalTicksProtoBuf(self, historicalTicksRequestProto: HistoricalTicksRequestProto):
+ if historicalTicksRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = historicalTicksRequestProto.reqId if historicalTicksRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = historicalTicksRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_HISTORICAL_TICKS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHISTORICALTICKS.code(), FAIL_SEND_REQHISTORICALTICKS.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Market Scanners
+ #########################################################################
+
+ def reqScannerParameters(self):
+ """Requests an XML string that describes all possible scanner queries."""
+ if self.useProtoBuf(OUT.REQ_SCANNER_PARAMETERS):
+ self.reqScannerParametersProtoBuf(createScannerParametersRequestProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = make_field(VERSION)
+
+ self.sendMsg(OUT.REQ_SCANNER_PARAMETERS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQSCANNERPARAMETERS.code(), FAIL_SEND_REQSCANNERPARAMETERS.msg() + str(ex))
+ return
+
+ def reqScannerParametersProtoBuf(self, scannerParametersRequestProto: ScannerParametersRequestProto):
+ if scannerParametersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = scannerParametersRequestProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.REQ_SCANNER_PARAMETERS + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQSCANNERPARAMETERS.code(), FAIL_SEND_REQSCANNERPARAMETERS.msg() + str(ex))
+ return
+
+ def reqScannerSubscription(
+ self,
+ reqId: int,
+ subscription: ScannerSubscription,
+ scannerSubscriptionOptions: TagValueList,
+ scannerSubscriptionFilterOptions: TagValueList,
+ ):
+ """reqId:int - The ticker ID. Must be a unique value.
+ scannerSubscription:ScannerSubscription - This structure contains
+ possible parameters used to filter results.
+ scannerSubscriptionOptions:TagValueList - For internal use only.
+ Use default value XYZ."""
+
+ if self.useProtoBuf(OUT.REQ_SCANNER_SUBSCRIPTION):
+ self.reqScannerSubscriptionProtoBuf(createScannerSubscriptionRequestProto(reqId, subscription, scannerSubscriptionOptions, scannerSubscriptionFilterOptions))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if (
+ self.serverVersion() < MIN_SERVER_VER_SCANNER_GENERIC_OPTS
+ and scannerSubscriptionFilterOptions is not None
+ ):
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support API scanner subscription generic filter options",
+ )
+ return
+
+ try:
+ VERSION = 4
+
+ flds = []
+
+ if self.serverVersion() < MIN_SERVER_VER_SCANNER_GENERIC_OPTS:
+ flds += [make_field(VERSION)]
+
+ flds += [
+ make_field(reqId),
+ make_field_handle_empty(subscription.numberOfRows),
+ make_field(subscription.instrument),
+ make_field(subscription.locationCode),
+ make_field(subscription.scanCode),
+ make_field_handle_empty(subscription.abovePrice),
+ make_field_handle_empty(subscription.belowPrice),
+ make_field_handle_empty(subscription.aboveVolume),
+ make_field_handle_empty(subscription.marketCapAbove),
+ make_field_handle_empty(subscription.marketCapBelow),
+ make_field(subscription.moodyRatingAbove),
+ make_field(subscription.moodyRatingBelow),
+ make_field(subscription.spRatingAbove),
+ make_field(subscription.spRatingBelow),
+ make_field(subscription.maturityDateAbove),
+ make_field(subscription.maturityDateBelow),
+ make_field_handle_empty(subscription.couponRateAbove),
+ make_field_handle_empty(subscription.couponRateBelow),
+ make_field(subscription.excludeConvertible),
+ make_field_handle_empty(
+ subscription.averageOptionVolumeAbove
+ ), # srv v25 and above
+ make_field(subscription.scannerSettingPairs), # srv v25 and above
+ make_field(subscription.stockTypeFilter),
+ ] # srv v27 and above
+
+ # send scannerSubscriptionFilterOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_SCANNER_GENERIC_OPTS:
+ scannerSubscriptionFilterOptionsStr = ""
+ if scannerSubscriptionFilterOptions:
+ for tagValueOpt in scannerSubscriptionFilterOptions:
+ scannerSubscriptionFilterOptionsStr += str(tagValueOpt)
+ flds += [make_field(scannerSubscriptionFilterOptionsStr)]
+
+ # send scannerSubscriptionOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ scannerSubscriptionOptionsStr = ""
+ if scannerSubscriptionOptions:
+ for tagValueOpt in scannerSubscriptionOptions:
+ scannerSubscriptionOptionsStr += str(tagValueOpt)
+ flds += [
+ make_field(scannerSubscriptionOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_SCANNER_SUBSCRIPTION, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSCANNER.code(), FAIL_SEND_REQSCANNER.msg() + str(ex))
+ return
+
+ def reqScannerSubscriptionProtoBuf(self, scannerSubscriptionRequestProto: ScannerSubscriptionRequestProto):
+ if scannerSubscriptionRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = scannerSubscriptionRequestProto.reqId if scannerSubscriptionRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = scannerSubscriptionRequestProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.REQ_SCANNER_SUBSCRIPTION + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSCANNER.code(), FAIL_SEND_REQSCANNER.msg() + str(ex))
+ return
+
+ def cancelScannerSubscription(self, reqId: int):
+ """reqId:int - The ticker ID. Must be a unique value."""
+
+ if self.useProtoBuf(OUT.CANCEL_SCANNER_SUBSCRIPTION):
+ self.cancelScannerSubscriptionProtoBuf(createCancelScannerSubscriptionProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+
+ self.sendMsg(OUT.CANCEL_SCANNER_SUBSCRIPTION, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANSCANNER.code(), FAIL_SEND_CANSCANNER.msg() + str(ex))
+ return
+
+ def cancelScannerSubscriptionProtoBuf(self, cancelScannerSubscriptionProto: CancelScannerSubscriptionProto):
+ if cancelScannerSubscriptionProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelScannerSubscriptionProto.reqId if cancelScannerSubscriptionProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelScannerSubscriptionProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.CANCEL_SCANNER_SUBSCRIPTION + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANSCANNER.code(), FAIL_SEND_CANSCANNER.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Real Time Bars
+ #########################################################################
+
+ def reqRealTimeBars(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ barSize: int,
+ whatToShow: str,
+ useRTH: bool,
+ realTimeBarsOptions: TagValueList,
+ ):
+ """Call the reqRealTimeBars() function to start receiving real time bar
+ results through the realtimeBar() EWrapper function.
+
+ reqId:TickerId - The id for the request. Must be a unique value. When the
+ data is received, it will be identified by this id. This is also
+ used when canceling the request.
+ contract:Contract - This object contains a description of the contract
+ for which real time bars are being requested
+ barSize:int - Currently only 5 second bars are supported, if any other
+ value is used, an exception will be thrown.
+ whatToShow:str - Determines the nature of the data extracted. Valid
+ values include:
+ TRADES
+ BID
+ ASK
+ MIDPOINT
+ useRTH:bool - Regular Trading Hours only. Valid values include:
+ 0 = all data available during the time span requested is returned,
+ including time intervals when the market in question was
+ outside of regular trading hours.
+ 1 = only data within the regular trading hours for the product
+ requested is returned, even if the time span falls
+ partially or completely outside.
+ realTimeBarOptions:TagValueList - For internal use only. Use default value XYZ.
+ """
+ if self.useProtoBuf(OUT.REQ_REAL_TIME_BARS):
+ realTimeBarsRequestProto = createRealTimeBarsRequestProto(reqId, contract, barSize, whatToShow, useRTH, realTimeBarsOptions)
+ self.reqRealTimeBarsProtoBuf(realTimeBarsRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ if contract.tradingClass:
+ self.wrapper.error(
+ reqId,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support conId and tradingClass parameter in reqRealTimeBars.",
+ )
+ return
+
+ try:
+ VERSION = 3
+
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.conId),
+ ]
+ flds += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.lastTradeDateOrContractMonth),
+ make_field_handle_empty(contract.strike),
+ make_field(contract.right),
+ make_field(contract.multiplier),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ ]
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.tradingClass),
+ ]
+ flds += [make_field(barSize), make_field(whatToShow), make_field(useRTH)]
+
+ # send realTimeBarsOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ realTimeBarsOptionsStr = ""
+ if realTimeBarsOptions:
+ for tagValueOpt in realTimeBarsOptions:
+ realTimeBarsOptionsStr += str(tagValueOpt)
+ flds += [
+ make_field(realTimeBarsOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_REAL_TIME_BARS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQRTBARS.code(), FAIL_SEND_REQRTBARS.msg() + str(ex))
+ return
+
+ def reqRealTimeBarsProtoBuf(self, realTimeBarsRequestProto: RealTimeBarsRequestProto):
+ if realTimeBarsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = realTimeBarsRequestProto.reqId if realTimeBarsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = realTimeBarsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_REAL_TIME_BARS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQRTBARS.code(), FAIL_SEND_REQRTBARS.msg() + str(ex))
+ return
+
+ def cancelRealTimeBars(self, reqId: TickerId):
+ """Call the cancelRealTimeBars() function to stop receiving real time bar results.
+
+ reqId:TickerId - The id that was specified in the call to reqRealTimeBars()."""
+
+ if self.useProtoBuf(OUT.CANCEL_REAL_TIME_BARS):
+ cancelRealTimeBarsProto = createCancelRealTimeBarsProto(reqId)
+ self.cancelRealTimeBarsProtoBuf(cancelRealTimeBarsProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 1
+
+ # send req mkt data msg
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.CANCEL_REAL_TIME_BARS, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANRTBARS.code(), FAIL_SEND_CANRTBARS.msg() + str(ex))
+ return
+
+ def cancelRealTimeBarsProtoBuf(self, cancelRealTimeBarsProto: CancelRealTimeBarsProto):
+ if cancelRealTimeBarsProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelRealTimeBarsProto.reqId if cancelRealTimeBarsProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelRealTimeBarsProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_REAL_TIME_BARS + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANRTBARS.code(), FAIL_SEND_CANRTBARS.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Fundamental Data
+ #########################################################################
+
+ def reqFundamentalData(
+ self,
+ reqId: TickerId,
+ contract: Contract,
+ reportType: str,
+ fundamentalDataOptions: TagValueList,
+ ):
+ """Call this function to receive fundamental data for
+ stocks. The appropriate market data subscription must be set up in
+ Account Management before you can receive this data.
+ Fundamental data will be returned at EWrapper.fundamentalData().
+
+ reqFundamentalData() can handle conid specified in the Contract object,
+ but not tradingClass or multiplier. This is because reqFundamentalData()
+ is used only for stocks and stocks do not have a multiplier and
+ trading class.
+
+ reqId:tickerId - The ID of the data request. Ensures that responses are
+ matched to requests if several requests are in process.
+ contract:Contract - This structure contains a description of the
+ contract for which fundamental data is being requested.
+ reportType:str - One of the following XML reports:
+ ReportSnapshot (company overview)
+ ReportsFinSummary (financial summary)
+ ReportRatios (financial ratios)
+ ReportsFinStatements (financial statements)
+ RESC (analyst estimates)"""
+
+ if self.useProtoBuf(OUT.REQ_FUNDAMENTAL_DATA):
+ self.reqFundamentalsDataProtoBuf(createFundamentalsDataRequestProto(reqId, contract, reportType, fundamentalDataOptions))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ VERSION = 2
+
+ if self.serverVersion() < MIN_SERVER_VER_FUNDAMENTAL_DATA:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support fundamental data request.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_TRADING_CLASS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support conId parameter in reqFundamentalData.",
+ )
+ return
+
+ flds = []
+ flds += [
+ make_field(VERSION),
+ make_field(reqId),
+ ]
+
+ # send contract fields
+ if self.serverVersion() >= MIN_SERVER_VER_TRADING_CLASS:
+ flds += [
+ make_field(contract.conId),
+ ]
+ flds += [
+ make_field(contract.symbol),
+ make_field(contract.secType),
+ make_field(contract.exchange),
+ make_field(contract.primaryExchange),
+ make_field(contract.currency),
+ make_field(contract.localSymbol),
+ make_field(reportType),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_LINKING:
+ fundDataOptStr = ""
+ tagValuesCount = (
+ len(fundamentalDataOptions) if fundamentalDataOptions else 0
+ )
+ if fundamentalDataOptions:
+ for fundDataOption in fundamentalDataOptions:
+ fundDataOptStr += str(fundDataOption)
+ flds += [make_field(tagValuesCount), make_field(fundDataOptStr)]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_FUNDAMENTAL_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQFUNDDATA.code(), FAIL_SEND_REQFUNDDATA.msg() + str(ex))
+ return
+
+ def reqFundamentalsDataProtoBuf(self, fundamentalsDataRequestProto: FundamentalsDataRequestProto):
+ if fundamentalsDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = fundamentalsDataRequestProto.reqId if fundamentalsDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = fundamentalsDataRequestProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.REQ_FUNDAMENTAL_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQFUNDDATA.code(), FAIL_SEND_REQFUNDDATA.msg() + str(ex))
+ return
+
+ def cancelFundamentalData(self, reqId: TickerId):
+ """Call this function to stop receiving fundamental data.
+
+ reqId:TickerId - The ID of the data request."""
+
+ if self.useProtoBuf(OUT.CANCEL_FUNDAMENTAL_DATA):
+ self.cancelFundamentalsDataProtoBuf(createCancelFundamentalsDataProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_FUNDAMENTAL_DATA:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support fundamental data request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+
+ self.sendMsg(OUT.CANCEL_FUNDAMENTAL_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANFUNDDATA.code(), FAIL_SEND_CANFUNDDATA.msg() + str(ex))
+ return
+
+ def cancelFundamentalsDataProtoBuf(self, cancelFundamentalsDataProto: CancelFundamentalsDataProto):
+ if cancelFundamentalsDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelFundamentalsDataProto.reqId if cancelFundamentalsDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelFundamentalsDataProto.SerializeToString()
+ self.sendMsgProtoBuf(OUT.CANCEL_FUNDAMENTAL_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANFUNDDATA.code(), FAIL_SEND_CANFUNDDATA.msg() + str(ex))
+ return
+
+ ########################################################################
+ # News
+ #########################################################################
+
+ def reqNewsProviders(self):
+ if self.useProtoBuf(OUT.REQ_NEWS_PROVIDERS):
+ self.reqNewsProvidersProtoBuf(createNewsProvidersRequestProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_NEWS_PROVIDERS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support news providers request.",
+ )
+ return
+
+ try:
+ self.sendMsg(OUT.REQ_NEWS_PROVIDERS, "")
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQNEWSPROVIDERS.code(), FAIL_SEND_REQNEWSPROVIDERS.msg() + str(ex))
+ return
+
+ def reqNewsProvidersProtoBuf(self, newsProvidersRequestProto: NewsProvidersRequestProto):
+ if newsProvidersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = newsProvidersRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_NEWS_PROVIDERS + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQNEWSPROVIDERS.code(), FAIL_SEND_REQNEWSPROVIDERS.msg() + str(ex))
+ return
+
+ def reqNewsArticle(
+ self,
+ reqId: int,
+ providerCode: str,
+ articleId: str,
+ newsArticleOptions: TagValueList,
+ ):
+ if self.useProtoBuf(OUT.REQ_NEWS_ARTICLE):
+ self.reqNewsArticleProtoBuf(createNewsArticleRequestProto(reqId, providerCode, articleId, newsArticleOptions))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_NEWS_ARTICLE:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support news article request.",
+ )
+ return
+
+ try:
+ flds = []
+
+ flds += [
+ make_field(reqId),
+ make_field(providerCode),
+ make_field(articleId),
+ ]
+
+ # send newsArticleOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_NEWS_QUERY_ORIGINS:
+ newsArticleOptionsStr = ""
+ if newsArticleOptions:
+ for tagValue in newsArticleOptions:
+ newsArticleOptionsStr += str(tagValue)
+ flds += [
+ make_field(newsArticleOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_NEWS_ARTICLE, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQNEWSARTICLE.code(), FAIL_SEND_REQNEWSARTICLE.msg() + str(ex))
+ return
+
+ def reqNewsArticleProtoBuf(self, newsArticleRequestProto: NewsArticleRequestProto):
+ if newsArticleRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = newsArticleRequestProto.reqId if newsArticleRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = newsArticleRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_NEWS_ARTICLE + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQNEWSARTICLE.code(), FAIL_SEND_REQNEWSARTICLE.msg() + str(ex))
+ return
+
+ def reqHistoricalNews(
+ self,
+ reqId: int,
+ conId: int,
+ providerCodes: str,
+ startDateTime: str,
+ endDateTime: str,
+ totalResults: int,
+ historicalNewsOptions: TagValueList,
+ ):
+ if self.useProtoBuf(OUT.REQ_HISTORICAL_NEWS):
+ self.reqHistoricalNewsProtoBuf(createHistoricalNewsRequestProto(reqId, conId, providerCodes, startDateTime, endDateTime, totalResults, historicalNewsOptions))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_HISTORICAL_NEWS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support historical news request.",
+ )
+ return
+
+ try:
+ flds = []
+
+ flds += [
+ make_field(reqId),
+ make_field(conId),
+ make_field(providerCodes),
+ make_field(startDateTime),
+ make_field(endDateTime),
+ make_field(totalResults),
+ ]
+
+ # send historicalNewsOptions parameter
+ if self.serverVersion() >= MIN_SERVER_VER_NEWS_QUERY_ORIGINS:
+ historicalNewsOptionsStr = ""
+ if historicalNewsOptions:
+ for tagValue in historicalNewsOptions:
+ historicalNewsOptionsStr += str(tagValue)
+ flds += [
+ make_field(historicalNewsOptionsStr),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_HISTORICAL_NEWS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQHISTORICALNEWS.code(), FAIL_SEND_REQHISTORICALNEWS.msg() + str(ex))
+ return
+
+ def reqHistoricalNewsProtoBuf(self, historicalNewsRequestProto: HistoricalNewsRequestProto):
+ if historicalNewsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = historicalNewsRequestProto.reqId if historicalNewsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = historicalNewsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_HISTORICAL_NEWS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQHISTORICALNEWS.code(), FAIL_SEND_REQHISTORICALNEWS.msg() + str(ex))
+ return
+
+ #########################################################################
+ # Display Groups
+ #########################################################################
+
+ def queryDisplayGroups(self, reqId: int):
+ """
+ API requests used to integrate with TWS color-grouped windows (display groups).
+ TWS color-grouped windows are identified by an integer number.
+ Currently, that number ranges from 1 to 7 and are mapped to specific colors, as indicated in TWS.
+
+ reqId:int - The unique number that will be associated with the
+ response"""
+ if (self.useProtoBuf(OUT.QUERY_DISPLAY_GROUPS)):
+ queryDisplayGroupsRequestProto = createQueryDisplayGroupsRequestProto(reqId)
+ self.queryDisplayGroupsProtoBuf(queryDisplayGroupsRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support queryDisplayGroups request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.QUERY_DISPLAY_GROUPS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_QUERYDISPLAYGROUPS.code(), FAIL_SEND_QUERYDISPLAYGROUPS.msg() + str(ex))
+ return
+
+ def queryDisplayGroupsProtoBuf(self, queryDisplayGroupsRequestProto: QueryDisplayGroupsRequestProto):
+ if queryDisplayGroupsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = queryDisplayGroupsRequestProto.reqId if queryDisplayGroupsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = queryDisplayGroupsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.QUERY_DISPLAY_GROUPS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_QUERYDISPLAYGROUPS.code(), FAIL_SEND_QUERYDISPLAYGROUPS.msg() + str(ex))
+ return
+
+ def subscribeToGroupEvents(self, reqId: int, groupId: int):
+ """reqId:int - The unique number associated with the notification.
+ groupId:int - The ID of the group, currently it is a number from 1 to 7.
+ This is the display group subscription request sent by the API to TWS."""
+
+ if (self.useProtoBuf(OUT.SUBSCRIBE_TO_GROUP_EVENTS)):
+ subscribeToGroupEventsRequestProto = createSubscribeToGroupEventsRequestProto(reqId, groupId)
+ self.subscribeToGroupEventsProtoBuf(subscribeToGroupEventsRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support subscribeToGroupEvents request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ + make_field(groupId)
+ )
+ self.sendMsg(OUT.SUBSCRIBE_TO_GROUP_EVENTS, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_SUBSCRIBETOGROUPEVENTS.code(), FAIL_SEND_SUBSCRIBETOGROUPEVENTS.msg() + str(ex))
+ return
+
+ def subscribeToGroupEventsProtoBuf(self, subscribeToGroupEventsRequestProto: SubscribeToGroupEventsRequestProto):
+ if subscribeToGroupEventsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = subscribeToGroupEventsRequestProto.reqId if subscribeToGroupEventsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = subscribeToGroupEventsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.SUBSCRIBE_TO_GROUP_EVENTS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_SUBSCRIBETOGROUPEVENTS.code(), FAIL_SEND_SUBSCRIBETOGROUPEVENTS.msg() + str(ex))
+ return
+
+ def updateDisplayGroup(self, reqId: int, contractInfo: str):
+ """reqId:int - The requestId specified in subscribeToGroupEvents().
+ contractInfo:str - The encoded value that uniquely represents the
+ contract in IB. Possible values include:
+
+ none = empty selection
+ contractID@exchange - any non-combination contract.
+ Examples: 8314@SMART for IBM SMART; 8314@ARCA for IBM @ARCA.
+ combo = if any combo is selected."""
+
+ if (self.useProtoBuf(OUT.UPDATE_DISPLAY_GROUP)):
+ updateDisplayGroupRequestProto = createUpdateDisplayGroupRequestProto(reqId, contractInfo)
+ self.updateDisplayGroupProtoBuf(updateDisplayGroupRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support updateDisplayGroup request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ + make_field(contractInfo)
+ )
+ self.sendMsg(OUT.UPDATE_DISPLAY_GROUP, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_UPDATEDISPLAYGROUP.code(), FAIL_SEND_UPDATEDISPLAYGROUP.msg() + str(ex))
+ return
+
+ def updateDisplayGroupProtoBuf(self, updateDisplayGroupRequestProto: UpdateDisplayGroupRequestProto):
+ if updateDisplayGroupRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = updateDisplayGroupRequestProto.reqId if updateDisplayGroupRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = updateDisplayGroupRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.UPDATE_DISPLAY_GROUP + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_UPDATEDISPLAYGROUP.code(), FAIL_SEND_UPDATEDISPLAYGROUP.msg() + str(ex))
+ return
+
+ def unsubscribeFromGroupEvents(self, reqId: int):
+ """reqId:int - The requestId specified in subscribeToGroupEvents()."""
+
+ if (self.useProtoBuf(OUT.UNSUBSCRIBE_FROM_GROUP_EVENTS)):
+ unsubscribeFromGroupEventsRequestProto = createUnsubscribeFromGroupEventsRequestProto(reqId)
+ self.unsubscribeFromGroupEventsProtoBuf(unsubscribeFromGroupEventsRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support unsubscribeFromGroupEvents request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(reqId)
+ )
+ self.sendMsg(OUT.UNSUBSCRIBE_FROM_GROUP_EVENTS, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS.code(), FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS.msg() + str(ex))
+ return
+
+ def unsubscribeFromGroupEventsProtoBuf(self, unsubscribeFromGroupEventsRequestProto: UnsubscribeFromGroupEventsRequestProto):
+ if unsubscribeFromGroupEventsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = unsubscribeFromGroupEventsRequestProto.reqId if unsubscribeFromGroupEventsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = unsubscribeFromGroupEventsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.UNSUBSCRIBE_FROM_GROUP_EVENTS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS.code(), FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS.msg() + str(ex))
+ return
+
+ def verifyRequest(self, apiName: str, apiVersion: str):
+ """For IB's internal purpose. Allows to provide means of verification
+ between the TWS and third party programs."""
+ if (self.useProtoBuf(OUT.VERIFY_REQUEST)):
+ verifyRequestProto = createVerifyRequestProto(apiName, apiVersion)
+ self.verifyRequestProtoBuf(verifyRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support verification request.",
+ )
+ return
+
+ if not self.extraAuth:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ FAIL_SEND_VERIFYMESSAGE.code(),
+ FAIL_SEND_VERIFYMESSAGE.msg()
+ + " Intent to authenticate needs to be expressed during initial connect request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(apiName)
+ + make_field(apiVersion)
+ )
+ self.sendMsg(OUT.VERIFY_REQUEST, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYREQUEST.code(), FAIL_SEND_VERIFYREQUEST.msg() + str(ex))
+ return
+
+ def verifyRequestProtoBuf(self, verifyRequestProto: VerifyRequestProto):
+ if verifyRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if not self.extraAuth:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYREQUEST.code(), FAIL_SEND_VERIFYREQUEST.msg() + " Intent to authenticate needs to be expressed during initial connect request.")
+ return
+
+ try:
+ serializedString = verifyRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.VERIFY_REQUEST + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYREQUEST.code(), FAIL_SEND_VERIFYREQUEST.msg() + str(ex))
+ return
+
+ def verifyMessage(self, apiData: str):
+ """For IB's internal purpose. Allows to provide means of verification
+ between the TWS and third party programs."""
+ if (self.useProtoBuf(OUT.VERIFY_MESSAGE)):
+ verifyMessageRequestProto = createVerifyMessageRequestProto(apiData)
+ self.verifyMessageProtoBuf(verifyMessageRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support verification request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(apiData)
+ )
+ self.sendMsg(OUT.VERIFY_MESSAGE, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYMESSAGE.code(), FAIL_SEND_VERIFYMESSAGE.msg() + str(ex))
+ return
+
+ def verifyMessageProtoBuf(self, verifyMessageRequestProto: VerifyMessageRequestProto):
+ if verifyMessageRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = verifyMessageRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.VERIFY_MESSAGE + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYMESSAGE.code(), FAIL_SEND_VERIFYMESSAGE.msg() + str(ex))
+ return
+
+ def verifyAndAuthRequest(self, apiName: str, apiVersion: str, opaqueIsvKey: str):
+ """For IB's internal purpose. Allows to provide means of verification
+ between the TWS and third party programs."""
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support verification request.",
+ )
+ return
+
+ if not self.extraAuth:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ FAIL_SEND_VERIFYANDAUTHREQUEST.code(),
+ FAIL_SEND_VERIFYANDAUTHREQUEST.msg()
+ + " Intent to authenticate needs to be expressed during initial connect request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(apiName)
+ + make_field(apiVersion)
+ + make_field(opaqueIsvKey)
+ )
+ self.sendMsg(OUT.VERIFY_AND_AUTH_REQUEST, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYANDAUTHREQUEST.code(), FAIL_SEND_VERIFYANDAUTHREQUEST.msg() + str(ex))
+ return
+
+ def verifyAndAuthMessage(self, apiData: str, xyzResponse: str):
+ """For IB's internal purpose. Allows to provide means of verification
+ between the TWS and third party programs."""
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_LINKING:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support verification request.",
+ )
+ return
+
+ try:
+ VERSION = 1
+
+ msg = (
+ make_field(VERSION)
+ + make_field(apiData)
+ + make_field(xyzResponse)
+ )
+ self.sendMsg(OUT.VERIFY_AND_AUTH_MESSAGE, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_VERIFYANDAUTHMESSAGE.code(), FAIL_SEND_VERIFYANDAUTHMESSAGE.msg() + str(ex))
+ return
+
+ def reqSecDefOptParams(
+ self,
+ reqId: int,
+ underlyingSymbol: str,
+ futFopExchange: str,
+ underlyingSecType: str,
+ underlyingConId: int,
+ ):
+ """Requests security definition option parameters for viewing a
+ contract's option chain reqId the ID chosen for the request
+ underlyingSymbol futFopExchange The exchange on which the returned
+ options are trading. Can be set to the empty string "" for all
+ exchanges. underlyingSecType The type of the underlying security,
+ i.e. STK underlyingConId the contract ID of the underlying security.
+ Response comes via EWrapper.securityDefinitionOptionParameter()"""
+
+ if self.useProtoBuf(OUT.REQ_SEC_DEF_OPT_PARAMS):
+ self.reqSecDefOptParamsProtoBuf(createSecDefOptParamsRequestProto(reqId, underlyingSymbol, futFopExchange, underlyingSecType, underlyingConId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support security definition option request.",
+ )
+ return
+
+ try:
+ flds = []
+ flds += [
+ make_field(reqId),
+ make_field(underlyingSymbol),
+ make_field(futFopExchange),
+ make_field(underlyingSecType),
+ make_field(underlyingConId),
+ ]
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_SEC_DEF_OPT_PARAMS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSECDEFOPTPARAMS.code(), FAIL_SEND_REQSECDEFOPTPARAMS.msg() + str(ex))
+ return
+
+ def reqSecDefOptParamsProtoBuf(self, secDefOptParamsRequestProto: SecDefOptParamsRequestProto):
+ if secDefOptParamsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = secDefOptParamsRequestProto.reqId if secDefOptParamsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = secDefOptParamsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_SEC_DEF_OPT_PARAMS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSECDEFOPTPARAMS.code(), FAIL_SEND_REQSECDEFOPTPARAMS.msg() + str(ex))
+ return
+
+ def reqSoftDollarTiers(self, reqId: int):
+ """Requests pre-defined Soft Dollar Tiers. This is only supported for
+ registered professional advisors and hedge and mutual funds who have
+ configured Soft Dollar Tiers in Account Management."""
+
+ if self.useProtoBuf(OUT.REQ_SOFT_DOLLAR_TIERS):
+ self.reqSoftDollarTiersProtoBuf(createSoftDollarTiersRequestProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.REQ_SOFT_DOLLAR_TIERS, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSOFTDOLLARTIERS.code(), FAIL_SEND_REQSOFTDOLLARTIERS.msg() + str(ex))
+ return
+
+ def reqSoftDollarTiersProtoBuf(self, softDollarTiersRequestProto: SoftDollarTiersRequestProto):
+ if softDollarTiersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = softDollarTiersRequestProto.reqId if softDollarTiersRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = softDollarTiersRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_SOFT_DOLLAR_TIERS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQSOFTDOLLARTIERS.code(), FAIL_SEND_REQSOFTDOLLARTIERS.msg() + str(ex))
+ return
+
+
+ def reqFamilyCodes(self):
+ if self.useProtoBuf(OUT.REQ_FAMILY_CODES):
+ self.reqFamilyCodesProtoBuf(createFamilyCodesRequestProto())
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_FAMILY_CODES:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support family codes request.",
+ )
+ return
+
+ try:
+ self.sendMsg(OUT.REQ_FAMILY_CODES, "")
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQFAMILYCODES.code(), FAIL_SEND_REQFAMILYCODES.msg() + str(ex))
+ return
+
+ def reqFamilyCodesProtoBuf(self, familyCodesRequestProto: FamilyCodesRequestProto):
+ if familyCodesRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = familyCodesRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_FAMILY_CODES + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQFAMILYCODES.code(), FAIL_SEND_REQFAMILYCODES.msg() + str(ex))
+ return
+
+ def reqMatchingSymbols(self, reqId: int, pattern: str):
+ if self.useProtoBuf(OUT.REQ_MATCHING_SYMBOLS):
+ self.reqMatchingSymbolsProtoBuf(createMatchingSymbolsRequestProto(reqId, pattern))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_REQ_MATCHING_SYMBOLS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support matching symbols request.",
+ )
+ return
+
+ try:
+ msg = (
+ make_field(reqId)
+ + make_field(pattern)
+ )
+ self.sendMsg(OUT.REQ_MATCHING_SYMBOLS, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMATCHINGSYMBOLS.code(), FAIL_SEND_REQMATCHINGSYMBOLS.msg() + str(ex))
+ return
+
+ def reqMatchingSymbolsProtoBuf(self, matchingSymbolsRequestProto: MatchingSymbolsRequestProto):
+ if matchingSymbolsRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = matchingSymbolsRequestProto.reqId if matchingSymbolsRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = matchingSymbolsRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_MATCHING_SYMBOLS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQMATCHINGSYMBOLS.code(), FAIL_SEND_REQMATCHINGSYMBOLS.msg() + str(ex))
+ return
+
+ def reqCompletedOrders(self, apiOnly: bool):
+ """Call this function to request the completed orders. If apiOnly parameter
+ is true, then only completed orders placed from API are requested.
+ Each completed order will be fed back through the
+ completedOrder() function on the EWrapper."""
+
+ if (self.useProtoBuf(OUT.REQ_COMPLETED_ORDERS)):
+ completedOrdersRequestProto = createCompletedOrdersRequestProto(apiOnly)
+ self.reqCompletedOrdersProtoBuf(completedOrdersRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ msg = make_field(apiOnly)
+
+ self.sendMsg(OUT.REQ_COMPLETED_ORDERS, msg)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQCOMPLETEDORDERS.code(), FAIL_SEND_REQCOMPLETEDORDERS.msg() + str(ex))
+ return
+
+ def reqCompletedOrdersProtoBuf(self, completedOrdersRequestProto: CompletedOrdersRequestProto):
+ if completedOrdersRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = completedOrdersRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_COMPLETED_ORDERS + PROTOBUF_MSG_ID, serializedString)
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQCOMPLETEDORDERS.code(), FAIL_SEND_REQCOMPLETEDORDERS.msg() + str(ex))
+ return
+
+ def reqWshMetaData(self, reqId: int):
+ if self.useProtoBuf(OUT.REQ_WSH_META_DATA):
+ self.reqWshMetaDataProtoBuf(createWshMetaDataRequestProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_WSHE_CALENDAR:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support WSHE Calendar API.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.REQ_WSH_META_DATA, msg)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQ_WSH_META_DATA.code(), FAIL_SEND_REQ_WSH_META_DATA.msg() + str(ex))
+ return
+
+ def reqWshMetaDataProtoBuf(self, wshMetaDataRequestProto: WshMetaDataRequestProto):
+ if wshMetaDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = wshMetaDataRequestProto.reqId if wshMetaDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = wshMetaDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_WSH_META_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQ_WSH_META_DATA.code(), FAIL_SEND_REQ_WSH_META_DATA.msg() + str(ex))
+ return
+
+ def cancelWshMetaData(self, reqId: int):
+ if self.useProtoBuf(OUT.CANCEL_WSH_META_DATA):
+ self.cancelWshMetaDataProtoBuf(createCancelWshMetaDataProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_WSHE_CALENDAR:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support WSHE Calendar API.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.CANCEL_WSH_META_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CAN_WSH_META_DATA.code(), FAIL_SEND_CAN_WSH_META_DATA.msg() + str(ex))
+ return
+
+ def cancelWshMetaDataProtoBuf(self, cancelWshMetaDataProto: CancelWshMetaDataProto):
+ if cancelWshMetaDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelWshMetaDataProto.reqId if cancelWshMetaDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelWshMetaDataProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_WSH_META_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CAN_WSH_META_DATA.code(), FAIL_SEND_CAN_WSH_META_DATA.msg() + str(ex))
+ return
+
+ def reqWshEventData(
+ self,
+ reqId: int,
+ wshEventData: WshEventData
+ ):
+ if self.useProtoBuf(OUT.REQ_WSH_EVENT_DATA):
+ self.reqWshEventDataProtoBuf(createWshEventDataRequestProto(reqId, wshEventData))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_WSHE_CALENDAR:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support WSHE Calendar API.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS:
+ if (
+ wshEventData.filter != ""
+ or wshEventData.fillWatchlist
+ or wshEventData.fillPortfolio
+ or wshEventData.fillCompetitors
+ ):
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support WSH event data filters.",
+ )
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE:
+ if (
+ wshEventData.startDate != ""
+ or wshEventData.endDate != ""
+ or wshEventData.totalLimit != UNSET_INTEGER
+ ):
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg()
+ + " It does not support WSH event data date filters.",
+ )
+ return
+
+ try:
+ flds = [
+ make_field(reqId),
+ make_field(wshEventData.conId),
+ ]
+
+ if self.serverVersion() >= MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS:
+ flds.append(make_field(wshEventData.filter))
+ flds.append(make_field(wshEventData.fillWatchlist))
+ flds.append(make_field(wshEventData.fillPortfolio))
+ flds.append(make_field(wshEventData.fillCompetitors))
+
+ if self.serverVersion() >= MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE:
+ flds.append(make_field(wshEventData.startDate))
+ flds.append(make_field(wshEventData.endDate))
+ flds.append(make_field(wshEventData.totalLimit))
+
+ msg = "".join(flds)
+ self.sendMsg(OUT.REQ_WSH_EVENT_DATA, msg)
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQ_WSH_EVENT_DATA.code(), FAIL_SEND_REQ_WSH_EVENT_DATA.msg() + str(ex))
+ return
+
+ def reqWshEventDataProtoBuf(self, wshEventDataRequestProto: WshEventDataRequestProto):
+ if wshEventDataRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = wshEventDataRequestProto.reqId if wshEventDataRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = wshEventDataRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_WSH_EVENT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQ_WSH_EVENT_DATA.code(), FAIL_SEND_REQ_WSH_EVENT_DATA.msg() + str(ex))
+ return
+
+ def cancelWshEventData(self, reqId: int):
+ if self.useProtoBuf(OUT.CANCEL_WSH_EVENT_DATA):
+ self.cancelWshEventDataProtoBuf(createCancelWshEventDataProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_WSHE_CALENDAR:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support WSHE Calendar API.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.CANCEL_WSH_EVENT_DATA, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CAN_WSH_EVENT_DATA.code(), FAIL_SEND_CAN_WSH_EVENT_DATA.msg() + str(ex))
+ return
+
+ def cancelWshEventDataProtoBuf(self, cancelWshEventDataProto: CancelWshEventDataProto):
+ if cancelWshEventDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelWshEventDataProto.reqId if cancelWshEventDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = cancelWshEventDataProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_WSH_EVENT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CAN_WSH_EVENT_DATA.code(), FAIL_SEND_CAN_WSH_EVENT_DATA.msg() + str(ex))
+ return
+
+ def reqUserInfo(self, reqId: int):
+ if self.useProtoBuf(OUT.REQ_USER_INFO):
+ self.reqUserInfoProtoBuf(createUserInfoRequestProto(reqId))
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_USER_INFO:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support user info requests.",
+ )
+ return
+
+ try:
+ msg = make_field(reqId)
+ self.sendMsg(OUT.REQ_USER_INFO, msg)
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQ_USER_INFO.code(), FAIL_SEND_REQ_USER_INFO.msg() + str(ex))
+ return
+
+ def reqUserInfoProtoBuf(self, userInfoRequestProto: UserInfoRequestProto):
+ if userInfoRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = userInfoRequestProto.reqId if userInfoRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = userInfoRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_USER_INFO + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQ_USER_INFO.code(), FAIL_SEND_REQ_USER_INFO.msg() + str(ex))
+ return
+
+ def reqCurrentTimeInMillis(self):
+ """Asks the current system time in milliseconds on the server side."""
+
+ if (self.useProtoBuf(OUT.REQ_CURRENT_TIME_IN_MILLIS)):
+ currentTimeInMillisRequestProto = createCurrentTimeInMillisRequestProto()
+ self.reqCurrentTimeInMillisProtoBuf(currentTimeInMillisRequestProto)
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CURRENT_TIME_IN_MILLIS:
+ self.wrapper.error(
+ NO_VALID_ID,
+ currentTimeMillis(),
+ UPDATE_TWS.code(),
+ UPDATE_TWS.msg() + " It does not support current time in millis requests.",
+ )
+ return
+
+ try:
+ self.sendMsg(OUT.REQ_CURRENT_TIME_IN_MILLIS, "")
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQCURRTIMEINMILLIS.code(), FAIL_SEND_REQCURRTIMEINMILLIS.msg() + str(ex))
+ return
+
+ def reqCurrentTimeInMillisProtoBuf(self, currentTimeInMillisRequestProto: CurrentTimeInMillisRequestProto):
+ if currentTimeInMillisRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ if not self.isConnected():
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ try:
+ serializedString = currentTimeInMillisRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_CURRENT_TIME_IN_MILLIS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_SEND_REQCURRTIMEINMILLIS.code(), FAIL_SEND_REQCURRTIMEINMILLIS.msg() + str(ex))
+ return
+
+ def cancelContractData(self, reqId: int):
+ cancelContractDataProto = createCancelContractDataProto(reqId)
+ self.cancelContractDataProtoBuf(cancelContractDataProto)
+
+ def cancelContractDataProtoBuf(self, cancelContractDataProto):
+ if cancelContractDataProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelContractDataProto.reqId if cancelContractDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CANCEL_CONTRACT_DATA:
+ self.wrapper.error(reqId, currentTimeMillis(), UPDATE_TWS.code(), UPDATE_TWS.msg() + " It does not support contract data cancels.")
+ return
+
+ try:
+ serializedString = cancelContractDataProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_CONTRACT_DATA + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCEL_CONTRACT_DATA.code(), FAIL_SEND_CANCEL_CONTRACT_DATA.msg() + str(ex))
+ return
+
+ def cancelHistoricalTicks(self, reqId: TickerId):
+ cancelHistoricalTicksProto = createCancelHistoricalTicksProto(reqId)
+ self.cancelHistoricalTicksProtoBuf(cancelHistoricalTicksProto)
+
+ def cancelHistoricalTicksProtoBuf(self, cancelHistoricalTicksProto):
+ if cancelHistoricalTicksProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = cancelHistoricalTicksProto.reqId if cancelHistoricalTicksProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CANCEL_CONTRACT_DATA:
+ self.wrapper.error(reqId, currentTimeMillis(), UPDATE_TWS.code(), UPDATE_TWS.msg() + " It does not support historical ticks cancels.")
+ return
+
+ try:
+ serializedString = cancelHistoricalTicksProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.CANCEL_HISTORICAL_TICKS + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_CANCEL_HISTORICAL_TICKS.code(), FAIL_SEND_CANCEL_HISTORICAL_TICKS.msg() + str(ex))
+ return
+
+ def reqConfigProtoBuf(self, configRequestProto: ConfigRequestProto):
+ if configRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = configRequestProto.reqId if configRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_CONFIG:
+ self.wrapper.error(reqId, currentTimeMillis(), UPDATE_TWS.code(), UPDATE_TWS.msg() + " It does not support config requests.")
+ return
+
+ try:
+ serializedString = configRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.REQ_CONFIG + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_REQCONFIG.code(), FAIL_SEND_REQCONFIG.msg() + str(ex))
+ return
+
+ def updateConfigProtoBuf(self, updateConfigRequestProto: UpdateConfigRequestProto):
+ if updateConfigRequestProto is None:
+ return
+
+ self.logRequest(current_fn_name(), vars())
+
+ reqId = updateConfigRequestProto.reqId if updateConfigRequestProto.HasField('reqId') else NO_VALID_ID
+
+ if not self.isConnected():
+ self.wrapper.error(reqId, currentTimeMillis(), NOT_CONNECTED.code(), NOT_CONNECTED.msg())
+ return
+
+ if self.serverVersion() < MIN_SERVER_VER_UPDATE_CONFIG:
+ self.wrapper.error(reqId, currentTimeMillis(), UPDATE_TWS.code(), UPDATE_TWS.msg() + " It does not support update config requests.")
+ return
+
+ try:
+ serializedString = updateConfigRequestProto.SerializeToString()
+
+ self.sendMsgProtoBuf(OUT.UPDATE_CONFIG + PROTOBUF_MSG_ID, serializedString)
+
+ except ClientException as ex:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ except Exception as ex:
+ self.wrapper.error(reqId, currentTimeMillis(), FAIL_SEND_UPDATECONFIG.code(), FAIL_SEND_UPDATECONFIG.msg() + str(ex))
+ return
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/client_utils.py b/packages/ibkr/ref/source/pythonclient/ibapi/client_utils.py
new file mode 100644
index 00000000..e322fcbf
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/client_utils.py
@@ -0,0 +1,1131 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.const import UNSET_DOUBLE
+from ibapi.execution import ExecutionFilter
+
+from ibapi.contract import Contract, DeltaNeutralContract, ComboLeg
+from ibapi.order import Order
+from ibapi.order_condition import OrderCondition, OperatorCondition, ContractCondition, PriceCondition, TimeCondition, MarginCondition, ExecutionCondition, VolumeCondition, PercentChangeCondition
+from ibapi.tag_value import TagValue
+from ibapi.utils import isValidIntValue, isValidFloatValue, isValidLongValue, isValidDecimalValue, decimalMaxString
+from ibapi.order_condition import Create
+from ibapi.common import TagValueList, WshEventData
+from ibapi.order_cancel import OrderCancel
+from ibapi.scanner import ScannerSubscription
+
+from ibapi.protobuf.ComboLeg_pb2 import ComboLeg as ComboLegProto
+from ibapi.protobuf.Contract_pb2 import Contract as ContractProto
+from ibapi.protobuf.DeltaNeutralContract_pb2 import DeltaNeutralContract as DeltaNeutralContractProto
+from ibapi.protobuf.OrderCancel_pb2 import OrderCancel as OrderCancelProto
+from ibapi.protobuf.OrderCondition_pb2 import OrderCondition as OrderConditionProto
+from ibapi.protobuf.PlaceOrderRequest_pb2 import PlaceOrderRequest as PlaceOrderRequestProto
+from ibapi.protobuf.CancelOrderRequest_pb2 import CancelOrderRequest as CancelOrderRequestProto
+from ibapi.protobuf.GlobalCancelRequest_pb2 import GlobalCancelRequest as GlobalCancelRequestProto
+from ibapi.protobuf.ExecutionFilter_pb2 import ExecutionFilter as ExecutionFilterProto
+from ibapi.protobuf.ExecutionRequest_pb2 import ExecutionRequest as ExecutionRequestProto
+from ibapi.protobuf.Order_pb2 import Order as OrderProto
+from ibapi.protobuf.SoftDollarTier_pb2 import SoftDollarTier as SoftDollarTierProto
+from ibapi.protobuf.AllOpenOrdersRequest_pb2 import AllOpenOrdersRequest as AllOpenOrdersRequestProto
+from ibapi.protobuf.AutoOpenOrdersRequest_pb2 import AutoOpenOrdersRequest as AutoOpenOrdersRequestProto
+from ibapi.protobuf.OpenOrdersRequest_pb2 import OpenOrdersRequest as OpenOrdersRequestProto
+from ibapi.protobuf.CompletedOrdersRequest_pb2 import CompletedOrdersRequest as CompletedOrdersRequestProto
+from ibapi.protobuf.ContractDataRequest_pb2 import ContractDataRequest as ContractDataRequestProto
+from ibapi.protobuf.MarketDataRequest_pb2 import MarketDataRequest as MarketDataRequestProto
+from ibapi.protobuf.CancelMarketData_pb2 import CancelMarketData as CancelMarketDataProto
+from ibapi.protobuf.MarketDepthRequest_pb2 import MarketDepthRequest as MarketDepthRequestProto
+from ibapi.protobuf.CancelMarketDepth_pb2 import CancelMarketDepth as CancelMarketDepthProto
+from ibapi.protobuf.MarketDataTypeRequest_pb2 import MarketDataTypeRequest as MarketDataTypeRequestProto
+from ibapi.protobuf.AccountDataRequest_pb2 import AccountDataRequest as AccountDataRequestProto
+from ibapi.protobuf.ManagedAccountsRequest_pb2 import ManagedAccountsRequest as ManagedAccountsRequestProto
+from ibapi.protobuf.PositionsRequest_pb2 import PositionsRequest as PositionsRequestProto
+from ibapi.protobuf.CancelPositions_pb2 import CancelPositions as CancelPositionsProto
+from ibapi.protobuf.AccountSummaryRequest_pb2 import AccountSummaryRequest as AccountSummaryRequestProto
+from ibapi.protobuf.CancelAccountSummary_pb2 import CancelAccountSummary as CancelAccountSummaryProto
+from ibapi.protobuf.PositionsMultiRequest_pb2 import PositionsMultiRequest as PositionsMultiRequestProto
+from ibapi.protobuf.CancelPositionsMulti_pb2 import CancelPositionsMulti as CancelPositionsMultiProto
+from ibapi.protobuf.AccountUpdatesMultiRequest_pb2 import AccountUpdatesMultiRequest as AccountUpdatesMultiRequestProto
+from ibapi.protobuf.CancelAccountUpdatesMulti_pb2 import CancelAccountUpdatesMulti as CancelAccountUpdatesMultiProto
+from ibapi.protobuf.HistoricalDataRequest_pb2 import HistoricalDataRequest as HistoricalDataRequestProto
+from ibapi.protobuf.RealTimeBarsRequest_pb2 import RealTimeBarsRequest as RealTimeBarsRequestProto
+from ibapi.protobuf.HeadTimestampRequest_pb2 import HeadTimestampRequest as HeadTimestampRequestProto
+from ibapi.protobuf.HistogramDataRequest_pb2 import HistogramDataRequest as HistogramDataRequestProto
+from ibapi.protobuf.HistoricalTicksRequest_pb2 import HistoricalTicksRequest as HistoricalTicksRequestProto
+from ibapi.protobuf.TickByTickRequest_pb2 import TickByTickRequest as TickByTickRequestProto
+from ibapi.protobuf.CancelHistoricalData_pb2 import CancelHistoricalData as CancelHistoricalDataProto
+from ibapi.protobuf.CancelRealTimeBars_pb2 import CancelRealTimeBars as CancelRealTimeBarsProto
+from ibapi.protobuf.CancelHeadTimestamp_pb2 import CancelHeadTimestamp as CancelHeadTimestampProto
+from ibapi.protobuf.CancelHistogramData_pb2 import CancelHistogramData as CancelHistogramDataProto
+from ibapi.protobuf.CancelTickByTick_pb2 import CancelTickByTick as CancelTickByTickProto
+from ibapi.protobuf.NewsBulletinsRequest_pb2 import NewsBulletinsRequest as NewsBulletinsRequestProto
+from ibapi.protobuf.CancelNewsBulletins_pb2 import CancelNewsBulletins as CancelNewsBulletinsProto
+from ibapi.protobuf.NewsArticleRequest_pb2 import NewsArticleRequest as NewsArticleRequestProto
+from ibapi.protobuf.NewsProvidersRequest_pb2 import NewsProvidersRequest as NewsProvidersRequestProto
+from ibapi.protobuf.HistoricalNewsRequest_pb2 import HistoricalNewsRequest as HistoricalNewsRequestProto
+from ibapi.protobuf.WshMetaDataRequest_pb2 import WshMetaDataRequest as WshMetaDataRequestProto
+from ibapi.protobuf.CancelWshMetaData_pb2 import CancelWshMetaData as CancelWshMetaDataProto
+from ibapi.protobuf.WshEventDataRequest_pb2 import WshEventDataRequest as WshEventDataRequestProto
+from ibapi.protobuf.CancelWshEventData_pb2 import CancelWshEventData as CancelWshEventDataProto
+from ibapi.protobuf.ScannerParametersRequest_pb2 import ScannerParametersRequest as ScannerParametersRequestProto
+from ibapi.protobuf.ScannerSubscriptionRequest_pb2 import ScannerSubscriptionRequest as ScannerSubscriptionRequestProto
+from ibapi.protobuf.ScannerSubscription_pb2 import ScannerSubscription as ScannerSubscriptionProto
+from ibapi.protobuf.FundamentalsDataRequest_pb2 import FundamentalsDataRequest as FundamentalsDataRequestProto
+from ibapi.protobuf.PnLRequest_pb2 import PnLRequest as PnLRequestProto
+from ibapi.protobuf.PnLSingleRequest_pb2 import PnLSingleRequest as PnLSingleRequestProto
+from ibapi.protobuf.CancelScannerSubscription_pb2 import CancelScannerSubscription as CancelScannerSubscriptionProto
+from ibapi.protobuf.CancelFundamentalsData_pb2 import CancelFundamentalsData as CancelFundamentalsDataProto
+from ibapi.protobuf.CancelPnL_pb2 import CancelPnL as CancelPnLProto
+from ibapi.protobuf.CancelPnLSingle_pb2 import CancelPnLSingle as CancelPnLSingleProto
+from ibapi.protobuf.FARequest_pb2 import FARequest as FARequestProto
+from ibapi.protobuf.FAReplace_pb2 import FAReplace as FAReplaceProto
+from ibapi.protobuf.ExerciseOptionsRequest_pb2 import ExerciseOptionsRequest as ExerciseOptionsRequestProto
+from ibapi.protobuf.CalculateImpliedVolatilityRequest_pb2 import CalculateImpliedVolatilityRequest as CalculateImpliedVolatilityRequestProto
+from ibapi.protobuf.CancelCalculateImpliedVolatility_pb2 import CancelCalculateImpliedVolatility as CancelCalculateImpliedVolatilityProto
+from ibapi.protobuf.CalculateOptionPriceRequest_pb2 import CalculateOptionPriceRequest as CalculateOptionPriceRequestProto
+from ibapi.protobuf.CancelCalculateOptionPrice_pb2 import CancelCalculateOptionPrice as CancelCalculateOptionPriceProto
+from ibapi.protobuf.SecDefOptParamsRequest_pb2 import SecDefOptParamsRequest as SecDefOptParamsRequestProto
+from ibapi.protobuf.SoftDollarTiersRequest_pb2 import SoftDollarTiersRequest as SoftDollarTiersRequestProto
+from ibapi.protobuf.FamilyCodesRequest_pb2 import FamilyCodesRequest as FamilyCodesRequestProto
+from ibapi.protobuf.MatchingSymbolsRequest_pb2 import MatchingSymbolsRequest as MatchingSymbolsRequestProto
+from ibapi.protobuf.SmartComponentsRequest_pb2 import SmartComponentsRequest as SmartComponentsRequestProto
+from ibapi.protobuf.MarketRuleRequest_pb2 import MarketRuleRequest as MarketRuleRequestProto
+from ibapi.protobuf.UserInfoRequest_pb2 import UserInfoRequest as UserInfoRequestProto
+from ibapi.protobuf.IdsRequest_pb2 import IdsRequest as IdsRequestProto
+from ibapi.protobuf.CurrentTimeRequest_pb2 import CurrentTimeRequest as CurrentTimeRequestProto
+from ibapi.protobuf.CurrentTimeInMillisRequest_pb2 import CurrentTimeInMillisRequest as CurrentTimeInMillisRequestProto
+from ibapi.protobuf.StartApiRequest_pb2 import StartApiRequest as StartApiRequestProto
+from ibapi.protobuf.SetServerLogLevelRequest_pb2 import SetServerLogLevelRequest as SetServerLogLevelRequestProto
+from ibapi.protobuf.VerifyRequest_pb2 import VerifyRequest as VerifyRequestProto
+from ibapi.protobuf.VerifyMessageRequest_pb2 import VerifyMessageRequest as VerifyMessageRequestProto
+from ibapi.protobuf.QueryDisplayGroupsRequest_pb2 import QueryDisplayGroupsRequest as QueryDisplayGroupsRequestProto
+from ibapi.protobuf.SubscribeToGroupEventsRequest_pb2 import SubscribeToGroupEventsRequest as SubscribeToGroupEventsRequestProto
+from ibapi.protobuf.UpdateDisplayGroupRequest_pb2 import UpdateDisplayGroupRequest as UpdateDisplayGroupRequestProto
+from ibapi.protobuf.UnsubscribeFromGroupEventsRequest_pb2 import UnsubscribeFromGroupEventsRequest as UnsubscribeFromGroupEventsRequestProto
+from ibapi.protobuf.MarketDepthExchangesRequest_pb2 import MarketDepthExchangesRequest as MarketDepthExchangesRequestProto
+from ibapi.protobuf.CancelContractData_pb2 import CancelContractData as CancelContractDataProto
+from ibapi.protobuf.CancelHistoricalTicks_pb2 import CancelHistoricalTicks as CancelHistoricalTicksProto
+from ibapi.protobuf.AttachedOrders_pb2 import AttachedOrders as AttachedOrdersProto
+
+from ibapi.errors import (
+ ERROR_ENCODING_PROTOBUF
+)
+from ibapi.utils import ClientException
+
+@staticmethod
+def createExecutionRequestProto(reqId: int, execFilter: ExecutionFilter) -> ExecutionRequestProto:
+ executionFilterProto = ExecutionFilterProto()
+ if isValidIntValue(execFilter.clientId): executionFilterProto.clientId = execFilter.clientId
+ if execFilter.acctCode: executionFilterProto.acctCode = execFilter.acctCode
+ if execFilter.time: executionFilterProto.time = execFilter.time
+ if execFilter.symbol: executionFilterProto.symbol = execFilter.symbol
+ if execFilter.secType: executionFilterProto.secType = execFilter.secType
+ if execFilter.exchange: executionFilterProto.exchange = execFilter.exchange
+ if execFilter.side: executionFilterProto.side = execFilter.side
+ if isValidIntValue(execFilter.lastNDays): executionFilterProto.lastNDays = execFilter.lastNDays
+ if execFilter.specificDates is not None and execFilter.specificDates: executionFilterProto.specificDates.extend(execFilter.specificDates)
+ executionRequestProto = ExecutionRequestProto()
+ if isValidIntValue(reqId): executionRequestProto.reqId = reqId
+ executionRequestProto.executionFilter.CopyFrom(executionFilterProto)
+ return executionRequestProto
+
+@staticmethod
+def createPlaceOrderRequestProto(orderId: int, contract: Contract, order: Order) -> PlaceOrderRequestProto:
+ placeOrderRequestProto = PlaceOrderRequestProto()
+ if isValidIntValue(orderId): placeOrderRequestProto.orderId = orderId
+ contractProto = createContractProto(contract, order)
+ if contractProto is not None: placeOrderRequestProto.contract.CopyFrom(contractProto)
+ orderProto = createOrderProto(order)
+ if orderProto is not None: placeOrderRequestProto.order.CopyFrom(orderProto)
+ attachedOrdersProto = createAttachedOrdersProto(order)
+ if attachedOrdersProto is not None: placeOrderRequestProto.attachedOrders.CopyFrom(attachedOrdersProto)
+ return placeOrderRequestProto
+
+@staticmethod
+def createAttachedOrdersProto(order: Order) -> AttachedOrdersProto:
+ attachedOrdersProto = AttachedOrdersProto()
+ if isValidIntValue(order.slOrderId): attachedOrdersProto.slOrderId = order.slOrderId
+ if order.slOrderType: attachedOrdersProto.slOrderType = order.slOrderType
+ if isValidIntValue(order.ptOrderId): attachedOrdersProto.ptOrderId = order.ptOrderId
+ if order.ptOrderType: attachedOrdersProto.ptOrderType = order.ptOrderType
+ return attachedOrdersProto
+
+@staticmethod
+def createContractProto(contract: Contract, order: Order) -> ContractProto:
+ contractProto = ContractProto()
+ if isValidIntValue(contract.conId): contractProto.conId = contract.conId
+ if contract.symbol: contractProto.symbol = contract.symbol
+ if contract.secType: contractProto.secType = contract.secType
+ if contract.lastTradeDateOrContractMonth: contractProto.lastTradeDateOrContractMonth = contract.lastTradeDateOrContractMonth
+ if isValidFloatValue(contract.strike): contractProto.strike = contract.strike
+ if contract.right: contractProto.right = contract.right
+ if contract.multiplier: contractProto.multiplier = float(contract.multiplier)
+ if contract.exchange: contractProto.exchange = contract.exchange
+ if contract.primaryExchange: contractProto.primaryExch = contract.primaryExchange
+ if contract.currency: contractProto.currency = contract.currency
+ if contract.localSymbol: contractProto.localSymbol = contract.localSymbol
+ if contract.tradingClass: contractProto.tradingClass = contract.tradingClass
+ if contract.secIdType: contractProto.secIdType = contract.secIdType
+ if contract.secId: contractProto.secId = contract.secId
+ if contract.includeExpired: contractProto.includeExpired = contract.includeExpired
+ if contract.comboLegsDescrip: contractProto.comboLegsDescrip = contract.comboLegsDescrip
+ if contract.description: contractProto.description = contract.description
+ if contract.issuerId: contractProto.issuerId = contract.issuerId
+
+ comboLegProtoList = createComboLegProtoList(contract, order)
+ if comboLegProtoList is not None and comboLegProtoList: contractProto.comboLegs.extend(comboLegProtoList)
+
+ deltaNeutralContractProto = createDeltaNeutralContractProto(contract)
+ if deltaNeutralContractProto is not None: contractProto.deltaNeutralContract.CopyFrom(deltaNeutralContractProto)
+
+ return contractProto
+
+@staticmethod
+def createDeltaNeutralContractProto(contract: Contract) -> DeltaNeutralContractProto:
+ deltaNeutralContractProto = None
+ if contract.deltaNeutralContract is not None:
+ deltaNeutralContract = contract.deltaNeutralContract
+ deltaNeutralContractProto = DeltaNeutralContractProto()
+ if isValidIntValue(deltaNeutralContract.conId): deltaNeutralContractProto.conId = deltaNeutralContract.conId
+ if isValidFloatValue(deltaNeutralContract.delta): deltaNeutralContractProto.delta = deltaNeutralContract.delta
+ if isValidFloatValue(deltaNeutralContract.price): deltaNeutralContractProto.price = deltaNeutralContract.price
+ return deltaNeutralContractProto
+
+
+@staticmethod
+def createComboLegProtoList(contract: Contract, order: Order) -> list[ComboLegProto]:
+ comboLegs = contract.comboLegs
+ orderComboLegs = order.orderComboLegs if order is not None else None
+ comboLegProtoList = []
+ if comboLegs is not None and comboLegs:
+ for i, comboLeg in enumerate(comboLegs):
+ perLegPrice = UNSET_DOUBLE
+ if orderComboLegs is not None and i < len(orderComboLegs):
+ perLegPrice = orderComboLegs[i].price
+ comboLegProto = createComboLegProto(comboLeg, perLegPrice)
+ comboLegProtoList.append(comboLegProto)
+ return comboLegProtoList
+
+@staticmethod
+def createComboLegProto(comboLeg: ComboLeg, perLegPrice: float) -> ComboLegProto:
+ comboLegProto = ComboLegProto()
+ if isValidIntValue(comboLeg.conId): comboLegProto.conId = comboLeg.conId
+ if isValidIntValue(comboLeg.ratio): comboLegProto.ratio = comboLeg.ratio
+ if comboLeg.action: comboLegProto.action = comboLeg.action
+ if comboLeg.exchange: comboLegProto.exchange = comboLeg.exchange
+ if isValidIntValue(comboLeg.openClose): comboLegProto.openClose = comboLeg.openClose
+ if isValidIntValue(comboLeg.shortSaleSlot): comboLegProto.shortSalesSlot = comboLeg.shortSaleSlot
+ if comboLeg.designatedLocation: comboLegProto.designatedLocation = comboLeg.designatedLocation
+ if isValidIntValue(comboLeg.exemptCode): comboLegProto.exemptCode = comboLeg.exemptCode
+ if isValidFloatValue(perLegPrice): comboLegProto.perLegPrice = perLegPrice
+ return comboLegProto
+
+@staticmethod
+def createOrderProto(order: Order) -> OrderProto:
+ orderProto = OrderProto()
+ if isValidIntValue(order.clientId): orderProto.clientId = order.clientId
+ if isValidLongValue(order.permId): orderProto.permId = order.permId
+ if isValidIntValue(order.parentId): orderProto.parentId = order.parentId
+ if order.action: orderProto.action = order.action
+ if isValidDecimalValue(order.totalQuantity): orderProto.totalQuantity = decimalMaxString(order.totalQuantity)
+ if isValidIntValue(order.displaySize): orderProto.displaySize = order.displaySize
+ if order.orderType: orderProto.orderType = order.orderType
+ if isValidFloatValue(order.lmtPrice): orderProto.lmtPrice = order.lmtPrice
+ if isValidFloatValue(order.auxPrice): orderProto.auxPrice = order.auxPrice
+ if order.tif: orderProto.tif = order.tif
+ if order.account: orderProto.account = order.account
+ if order.settlingFirm: orderProto.settlingFirm = order.settlingFirm
+ if order.clearingAccount: orderProto.clearingAccount = order.clearingAccount
+ if order.clearingIntent: orderProto.clearingIntent = order.clearingIntent
+ if order.allOrNone: orderProto.allOrNone = order.allOrNone
+ if order.blockOrder: orderProto.blockOrder = order.blockOrder
+ if order.hidden: orderProto.hidden = order.hidden
+ if order.outsideRth: orderProto.outsideRth = order.outsideRth
+ if order.sweepToFill: orderProto.sweepToFill = order.sweepToFill
+ if isValidFloatValue(order.percentOffset): orderProto.percentOffset = order.percentOffset
+ if isValidFloatValue(order.trailingPercent): orderProto.trailingPercent = order.trailingPercent
+ if isValidFloatValue(order.trailStopPrice): orderProto.trailStopPrice = order.trailStopPrice
+ if isValidIntValue(order.minQty): orderProto.minQty = order.minQty
+ if order.goodAfterTime: orderProto.goodAfterTime = order.goodAfterTime
+ if order.goodTillDate: orderProto.goodTillDate = order.goodTillDate
+ if order.ocaGroup: orderProto.ocaGroup = order.ocaGroup
+ if order.orderRef: orderProto.orderRef = order.orderRef
+ if order.rule80A: orderProto.rule80A = order.rule80A
+ if isValidIntValue(order.ocaType): orderProto.ocaType = order.ocaType
+ if isValidIntValue(order.triggerMethod): orderProto.triggerMethod = order.triggerMethod
+ if order.activeStartTime: orderProto.activeStartTime = order.activeStartTime
+ if order.activeStopTime: orderProto.activeStopTime = order.activeStopTime
+ if order.faGroup: orderProto.faGroup = order.faGroup
+ if order.faMethod: orderProto.faMethod = order.faMethod
+ if order.faPercentage: orderProto.faPercentage = order.faPercentage
+ if isValidFloatValue(order.volatility): orderProto.volatility = order.volatility
+ if isValidIntValue(order.volatilityType): orderProto.volatilityType = order.volatilityType
+ if order.continuousUpdate: orderProto.continuousUpdate = order.continuousUpdate
+ if isValidIntValue(order.referencePriceType): orderProto.referencePriceType = order.referencePriceType
+ if order.deltaNeutralOrderType: orderProto.deltaNeutralOrderType = order.deltaNeutralOrderType
+ if isValidFloatValue(order.deltaNeutralAuxPrice): orderProto.deltaNeutralAuxPrice = order.deltaNeutralAuxPrice
+ if isValidIntValue(order.deltaNeutralConId): orderProto.deltaNeutralConId = order.deltaNeutralConId
+ if order.deltaNeutralOpenClose: orderProto.deltaNeutralOpenClose = order.deltaNeutralOpenClose
+ if order.deltaNeutralShortSale: orderProto.deltaNeutralShortSale = order.deltaNeutralShortSale
+ if isValidIntValue(order.deltaNeutralShortSaleSlot): orderProto.deltaNeutralShortSaleSlot = order.deltaNeutralShortSaleSlot
+ if order.deltaNeutralDesignatedLocation: orderProto.deltaNeutralDesignatedLocation = order.deltaNeutralDesignatedLocation
+ if isValidIntValue(order.scaleInitLevelSize): orderProto.scaleInitLevelSize = order.scaleInitLevelSize
+ if isValidIntValue(order.scaleSubsLevelSize): orderProto.scaleSubsLevelSize = order.scaleSubsLevelSize
+ if isValidFloatValue(order.scalePriceIncrement): orderProto.scalePriceIncrement = order.scalePriceIncrement
+ if isValidFloatValue(order.scalePriceAdjustValue): orderProto.scalePriceAdjustValue = order.scalePriceAdjustValue
+ if isValidIntValue(order.scalePriceAdjustInterval): orderProto.scalePriceAdjustInterval = order.scalePriceAdjustInterval
+ if isValidFloatValue(order.scaleProfitOffset): orderProto.scaleProfitOffset = order.scaleProfitOffset
+ if order.scaleAutoReset: orderProto.scaleAutoReset = order.scaleAutoReset
+ if isValidIntValue(order.scaleInitPosition): orderProto.scaleInitPosition = order.scaleInitPosition
+ if isValidIntValue(order.scaleInitFillQty): orderProto.scaleInitFillQty = order.scaleInitFillQty
+ if order.scaleRandomPercent: orderProto.scaleRandomPercent = order.scaleRandomPercent
+ if order.scaleTable: orderProto.scaleTable = order.scaleTable
+ if order.hedgeType: orderProto.hedgeType = order.hedgeType
+ if order.hedgeParam: orderProto.hedgeParam = order.hedgeParam
+
+ if order.algoStrategy: orderProto.algoStrategy = order.algoStrategy
+ fillTagValueList(order.algoParams, orderProto.algoParams)
+ if order.algoId: orderProto.algoId = order.algoId
+
+ fillTagValueList(order.smartComboRoutingParams, orderProto.smartComboRoutingParams)
+
+ if order.whatIf: orderProto.whatIf = order.whatIf
+ if order.transmit: orderProto.transmit = order.transmit
+ if order.overridePercentageConstraints: orderProto.overridePercentageConstraints = order.overridePercentageConstraints
+ if order.openClose: orderProto.openClose = order.openClose
+ if isValidIntValue(order.origin): orderProto.origin = order.origin
+ if isValidIntValue(order.shortSaleSlot): orderProto.shortSaleSlot = order.shortSaleSlot
+ if order.designatedLocation: orderProto.designatedLocation = order.designatedLocation
+ if isValidIntValue(order.exemptCode): orderProto.exemptCode = order.exemptCode
+ if order.deltaNeutralSettlingFirm: orderProto.deltaNeutralSettlingFirm = order.deltaNeutralSettlingFirm
+ if order.deltaNeutralClearingAccount: orderProto.deltaNeutralClearingAccount = order.deltaNeutralClearingAccount
+ if order.deltaNeutralClearingIntent: orderProto.deltaNeutralClearingIntent = order.deltaNeutralClearingIntent
+ if isValidIntValue(order.discretionaryAmt): orderProto.discretionaryAmt = order.discretionaryAmt
+ if order.optOutSmartRouting: orderProto.optOutSmartRouting = order.optOutSmartRouting
+ if isValidIntValue(order.exemptCode): orderProto.exemptCode = order.exemptCode
+ if isValidFloatValue(order.startingPrice): orderProto.startingPrice = order.startingPrice
+ if isValidFloatValue(order.stockRefPrice): orderProto.stockRefPrice = order.stockRefPrice
+ if isValidFloatValue(order.delta): orderProto.delta = order.delta
+ if isValidFloatValue(order.stockRangeLower): orderProto.stockRangeLower = order.stockRangeLower
+ if isValidFloatValue(order.stockRangeUpper): orderProto.stockRangeUpper = order.stockRangeUpper
+ if order.notHeld: orderProto.notHeld = order.notHeld
+
+ fillTagValueList(order.orderMiscOptions, orderProto.orderMiscOptions)
+
+ if order.solicited: orderProto.solicited = order.solicited
+ if order.randomizeSize: orderProto.randomizeSize = order.randomizeSize
+ if order.randomizePrice: orderProto.randomizePrice = order.randomizePrice
+ if isValidIntValue(order.referenceContractId): orderProto.referenceContractId = order.referenceContractId
+ if isValidFloatValue(order.peggedChangeAmount): orderProto.peggedChangeAmount = order.peggedChangeAmount
+ if order.isPeggedChangeAmountDecrease: orderProto.isPeggedChangeAmountDecrease = order.isPeggedChangeAmountDecrease
+ if isValidFloatValue(order.referenceChangeAmount): orderProto.referenceChangeAmount = order.referenceChangeAmount
+ if order.referenceExchangeId: orderProto.referenceExchangeId = order.referenceExchangeId
+ if order.adjustedOrderType: orderProto.adjustedOrderType = order.adjustedOrderType
+ if isValidFloatValue(order.triggerPrice): orderProto.triggerPrice = order.triggerPrice
+ if isValidFloatValue(order.adjustedStopPrice): orderProto.adjustedStopPrice = order.adjustedStopPrice
+ if isValidFloatValue(order.adjustedStopLimitPrice): orderProto.adjustedStopLimitPrice = order.adjustedStopLimitPrice
+ if isValidFloatValue(order.adjustedTrailingAmount): orderProto.adjustedTrailingAmount = order.adjustedTrailingAmount
+ if isValidIntValue(order.adjustableTrailingUnit): orderProto.adjustableTrailingUnit = order.adjustableTrailingUnit
+ if isValidFloatValue(order.lmtPriceOffset): orderProto.lmtPriceOffset = order.lmtPriceOffset
+
+ orderConditionList = createConditionsProto(order)
+ if orderConditionList is not None and orderConditionList: orderProto.conditions.extend(orderConditionList)
+ if order.conditionsCancelOrder: orderProto.conditionsCancelOrder = order.conditionsCancelOrder
+ if order.conditionsIgnoreRth: orderProto.conditionsIgnoreRth = order.conditionsIgnoreRth
+
+ if order.modelCode: orderProto.modelCode = order.modelCode
+ if order.extOperator: orderProto.extOperator = order.extOperator
+
+ softDollarTier = createSoftDollarTierProto(order)
+ if softDollarTier is not None: orderProto.softDollarTier.CopyFrom(softDollarTier)
+
+ if isValidFloatValue(order.cashQty): orderProto.cashQty = order.cashQty
+ if order.mifid2DecisionMaker: orderProto.mifid2DecisionMaker = order.mifid2DecisionMaker
+ if order.mifid2DecisionAlgo: orderProto.mifid2DecisionAlgo = order.mifid2DecisionAlgo
+ if order.mifid2ExecutionTrader: orderProto.mifid2ExecutionTrader = order.mifid2ExecutionTrader
+ if order.mifid2ExecutionAlgo: orderProto.mifid2ExecutionAlgo = order.mifid2ExecutionAlgo
+ if order.dontUseAutoPriceForHedge: orderProto.dontUseAutoPriceForHedge = order.dontUseAutoPriceForHedge
+ if order.isOmsContainer: orderProto.isOmsContainer = order.isOmsContainer
+ if order.discretionaryUpToLimitPrice: orderProto.discretionaryUpToLimitPrice = order.discretionaryUpToLimitPrice
+ if order.usePriceMgmtAlgo is not None: orderProto.usePriceMgmtAlgo = 1 if order.usePriceMgmtAlgo else 0
+ if isValidIntValue(order.duration): orderProto.duration = order.duration
+ if isValidIntValue(order.postToAts): orderProto.postToAts = order.postToAts
+ if order.advancedErrorOverride: orderProto.advancedErrorOverride = order.advancedErrorOverride
+ if order.manualOrderTime: orderProto.manualOrderTime = order.manualOrderTime
+ if isValidIntValue(order.minTradeQty): orderProto.minTradeQty = order.minTradeQty
+ if isValidIntValue(order.minCompeteSize): orderProto.minCompeteSize = order.minCompeteSize
+ if isValidFloatValue(order.competeAgainstBestOffset): orderProto.competeAgainstBestOffset = order.competeAgainstBestOffset
+ if isValidFloatValue(order.midOffsetAtWhole): orderProto.midOffsetAtWhole = order.midOffsetAtWhole
+ if isValidFloatValue(order.midOffsetAtHalf): orderProto.midOffsetAtHalf = order.midOffsetAtHalf
+ if order.customerAccount: orderProto.customerAccount = order.customerAccount
+ if order.professionalCustomer: orderProto.professionalCustomer = order.professionalCustomer
+ if order.bondAccruedInterest: orderProto.bondAccruedInterest = order.bondAccruedInterest
+ if order.includeOvernight: orderProto.includeOvernight = order.includeOvernight
+ if isValidIntValue(order.manualOrderIndicator): orderProto.manualOrderIndicator = order.manualOrderIndicator
+ if order.submitter: orderProto.submitter = order.submitter
+ if order.autoCancelParent: orderProto.autoCancelParent = order.autoCancelParent
+ if order.imbalanceOnly: orderProto.imbalanceOnly = order.imbalanceOnly
+ if order.postOnly: orderProto.postOnly = order.postOnly
+ if order.allowPreOpen: orderProto.allowPreOpen = order.allowPreOpen
+ if order.ignoreOpenAuction: orderProto.ignoreOpenAuction = order.ignoreOpenAuction
+ if order.deactivate: orderProto.deactivate = order.deactivate
+ if order.seekPriceImprovement is not None: orderProto.seekPriceImprovement = 1 if order.seekPriceImprovement else 0
+ if isValidIntValue(order.whatIfType): orderProto.whatIfType = order.whatIfType
+ if order.routeMarketableToBbo is not None: orderProto.routeMarketableToBbo = 1 if order.routeMarketableToBbo else 0
+
+ return orderProto
+
+def createConditionsProto(order: Order) -> list[OrderConditionProto]:
+ orderConditionProtoList = []
+ try:
+ if order.conditions is not None and order.conditions:
+ for orderCondition in order.conditions:
+ conditionType = orderCondition.condType
+
+ if OrderCondition.Price == conditionType:
+ orderConditionProto = createPriceConditionProto(orderCondition)
+ elif OrderCondition.Time == conditionType:
+ orderConditionProto = createTimeConditionProto(orderCondition)
+ elif OrderCondition.Margin == conditionType:
+ orderConditionProto = createMarginConditionProto(orderCondition)
+ elif OrderCondition.Execution == conditionType:
+ orderConditionProto = createExecutionConditionProto(orderCondition)
+ elif OrderCondition.Volume == conditionType:
+ orderConditionProto = createVolumeConditionProto(orderCondition)
+ elif OrderCondition.PercentChange == conditionType:
+ orderConditionProto = createPercentChangeConditionProto(orderCondition)
+
+ if orderConditionProto is not None: orderConditionProtoList.append(orderConditionProto)
+
+ except Exception:
+ raise ClientException(ERROR_ENCODING_PROTOBUF.code(), ERROR_ENCODING_PROTOBUF.msg(), "Error encoding conditions")
+
+ return orderConditionProtoList
+
+@staticmethod
+def createOrderConditionProto(orderCondition: OrderCondition) -> OrderConditionProto:
+ conditionType = orderCondition.condType
+ isConjunctionConnection = orderCondition.isConjunctionConnection
+ orderConditionProto = OrderConditionProto()
+ if isValidIntValue(conditionType): orderConditionProto.type = conditionType
+ orderConditionProto.isConjunctionConnection = isConjunctionConnection
+ return orderConditionProto
+
+@staticmethod
+def createOperatorConditionProto(operatorCondition: OperatorCondition) -> OrderConditionProto:
+ orderConditionProto = createOrderConditionProto(operatorCondition)
+ operatorConditionProto = OrderConditionProto()
+ operatorConditionProto.MergeFrom(orderConditionProto)
+ operatorConditionProto.isMore = operatorCondition.isMore
+ return operatorConditionProto
+
+@staticmethod
+def createContractConditionProto(contractCondition: ContractCondition) -> OrderConditionProto:
+ operatorConditionProto = createOperatorConditionProto(contractCondition)
+ contractConditionProto = OrderConditionProto()
+ contractConditionProto.MergeFrom(operatorConditionProto)
+ if isValidIntValue(contractCondition.conId): contractConditionProto.conId = contractCondition.conId
+ if contractCondition.exchange: contractConditionProto.exchange = contractCondition.exchange
+ return contractConditionProto
+
+@staticmethod
+def createPriceConditionProto(priceCondition: PriceCondition) -> OrderConditionProto:
+ contractConditionProto = createContractConditionProto(priceCondition)
+ priceConditionProto = OrderConditionProto()
+ priceConditionProto.MergeFrom(contractConditionProto)
+ if isValidFloatValue(priceCondition.price): priceConditionProto.price = priceCondition.price
+ if isValidIntValue(priceCondition.triggerMethod): priceConditionProto.triggerMethod = priceCondition.triggerMethod
+ return priceConditionProto
+
+@staticmethod
+def createTimeConditionProto(timeCondition: TimeCondition) -> OrderConditionProto:
+ operatorConditionProto = createOperatorConditionProto(timeCondition)
+ timeConditionProto = OrderConditionProto()
+ timeConditionProto.MergeFrom(operatorConditionProto)
+ if timeCondition.time: timeConditionProto.time = timeCondition.time
+ return timeConditionProto
+
+@staticmethod
+def createMarginConditionProto(marginCondition: MarginCondition) -> OrderConditionProto:
+ operatorConditionProto = createOperatorConditionProto(marginCondition)
+ marginConditionProto = OrderConditionProto()
+ marginConditionProto.MergeFrom(operatorConditionProto)
+ if isValidFloatValue(marginCondition.percent): marginConditionProto.percent = marginCondition.percent
+ return marginConditionProto
+
+@staticmethod
+def createExecutionConditionProto(executionCondition: ExecutionCondition) -> OrderConditionProto:
+ orderConditionProto = createOrderConditionProto(executionCondition)
+ executionConditionProto = OrderConditionProto()
+ executionConditionProto.MergeFrom(orderConditionProto)
+ if executionCondition.secType: executionConditionProto.secType = executionCondition.secType
+ if executionCondition.exchange: executionConditionProto.exchange = executionCondition.exchange
+ if executionCondition.symbol: executionConditionProto.symbol = executionCondition.symbol
+ return executionConditionProto
+
+@staticmethod
+def createVolumeConditionProto(volumeCondition: VolumeCondition) -> OrderConditionProto:
+ contractConditionProto = createContractConditionProto(volumeCondition)
+ volumeConditionProto = OrderConditionProto()
+ volumeConditionProto.MergeFrom(contractConditionProto)
+ if isValidIntValue(volumeCondition.volume): volumeConditionProto.volume = volumeCondition.volume
+ return volumeConditionProto
+
+@staticmethod
+def createPercentChangeConditionProto(percentChangeCondition: PercentChangeCondition) -> OrderConditionProto:
+ contractConditionProto = createContractConditionProto(percentChangeCondition)
+ percentChangeConditionProto = OrderConditionProto()
+ percentChangeConditionProto.MergeFrom(contractConditionProto)
+ if isValidFloatValue(percentChangeCondition.changePercent): percentChangeConditionProto.changePercent = percentChangeCondition.changePercent
+ return percentChangeConditionProto
+
+@staticmethod
+def createSoftDollarTierProto(order: Order) -> SoftDollarTierProto:
+ softDollarTierProto = None
+ tier = order.softDollarTier
+ if tier is not None:
+ softDollarTierProto = SoftDollarTierProto()
+ if tier.name: softDollarTierProto.name = tier.name
+ if tier.val: softDollarTierProto.value = tier.val
+ if tier.displayName: softDollarTierProto.displayName = tier.displayName
+ return softDollarTierProto
+
+@staticmethod
+def fillTagValueList(tagValueList: list, orderProtoMap: dict):
+ if tagValueList is not None and tagValueList:
+ for tagValue in tagValueList:
+ orderProtoMap[tagValue.tag] = tagValue.value
+
+@staticmethod
+def createCancelOrderRequestProto(orderId: int, orderCancel: OrderCancel) -> CancelOrderRequestProto:
+ cancelOrderRequestProto = CancelOrderRequestProto()
+ if isValidIntValue(orderId): cancelOrderRequestProto.orderId = orderId
+ orderCancelProto = createOrderCancelProto(orderCancel)
+ if orderCancelProto is not None: cancelOrderRequestProto.orderCancel.CopyFrom(orderCancelProto)
+ return cancelOrderRequestProto
+
+@staticmethod
+def createGlobalCancelRequestProto(orderCancel: OrderCancel) -> GlobalCancelRequestProto:
+ globalCancelRequestProto = GlobalCancelRequestProto()
+ orderCancelProto = createOrderCancelProto(orderCancel)
+ if orderCancelProto is not None: globalCancelRequestProto.orderCancel.CopyFrom(orderCancelProto)
+ return globalCancelRequestProto
+
+@staticmethod
+def createOrderCancelProto(orderCancel: OrderCancel) -> OrderCancelProto:
+ if orderCancel is None:
+ return None
+ orderCancelProto = OrderCancelProto()
+ if orderCancel.manualOrderCancelTime: orderCancelProto.manualOrderCancelTime = orderCancel.manualOrderCancelTime
+ if orderCancel.extOperator: orderCancelProto.extOperator = orderCancel.extOperator
+ if isValidIntValue(orderCancel.manualOrderIndicator): orderCancelProto.manualOrderIndicator = orderCancel.manualOrderIndicator
+ return orderCancelProto
+
+@staticmethod
+def createAllOpenOrdersRequestProto() -> AllOpenOrdersRequestProto:
+ allOpenOrdersRequestProto = AllOpenOrdersRequestProto()
+ return allOpenOrdersRequestProto
+
+@staticmethod
+def createAutoOpenOrdersRequestProto(autoBind: bool) -> AutoOpenOrdersRequestProto:
+ autoOpenOrdersRequestProto = AutoOpenOrdersRequestProto()
+ if autoBind: autoOpenOrdersRequestProto.autoBind = autoBind
+ return autoOpenOrdersRequestProto
+
+@staticmethod
+def createOpenOrdersRequestProto() -> OpenOrdersRequestProto:
+ openOrdersRequestProto = OpenOrdersRequestProto()
+ return openOrdersRequestProto
+
+@staticmethod
+def createCompletedOrdersRequestProto(apiOnly: bool) -> CompletedOrdersRequestProto:
+ completedOrdersRequestProto = CompletedOrdersRequestProto()
+ if apiOnly: completedOrdersRequestProto.apiOnly = apiOnly
+ return completedOrdersRequestProto
+
+@staticmethod
+def createContractDataRequestProto(reqId: int, contract: Contract) -> ContractDataRequestProto:
+ contractDataRequestProto = ContractDataRequestProto()
+ if isValidIntValue(reqId): contractDataRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: contractDataRequestProto.contract.CopyFrom(contractProto)
+ return contractDataRequestProto
+
+@staticmethod
+def createMarketDataRequestProto(reqId: int, contract: Contract, genericTickList: str, snapshot: bool, regulatorySnapshot: bool, marketDataOptionsList: TagValueList) -> MarketDataRequestProto:
+ marketDataRequestProto = MarketDataRequestProto()
+ if isValidIntValue(reqId): marketDataRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: marketDataRequestProto.contract.CopyFrom(contractProto)
+ if genericTickList: marketDataRequestProto.genericTickList = genericTickList
+ if snapshot: marketDataRequestProto.snapshot = snapshot
+ if regulatorySnapshot: marketDataRequestProto.regulatorySnapshot = regulatorySnapshot
+ fillTagValueList(marketDataOptionsList, marketDataRequestProto.marketDataOptions)
+ return marketDataRequestProto
+
+@staticmethod
+def createMarketDepthRequestProto(reqId: int, contract: Contract, numRows: int, isSmartDepth: bool, marketDepthOptionsList: TagValueList) -> MarketDepthRequestProto:
+ marketDepthRequestProto = MarketDepthRequestProto()
+ if isValidIntValue(reqId): marketDepthRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: marketDepthRequestProto.contract.CopyFrom(contractProto)
+ if isValidIntValue(numRows): marketDepthRequestProto.numRows = numRows
+ if isSmartDepth: marketDepthRequestProto.isSmartDepth = isSmartDepth
+ fillTagValueList(marketDepthOptionsList, marketDepthRequestProto.marketDepthOptions)
+ return marketDepthRequestProto
+
+@staticmethod
+def createMarketDataTypeRequestProto(marketDataType: int) -> MarketDataTypeRequestProto:
+ marketDataTypeRequestProto = MarketDataTypeRequestProto()
+ if isValidIntValue(marketDataType): marketDataTypeRequestProto.marketDataType = marketDataType
+ return marketDataTypeRequestProto
+
+@staticmethod
+def createCancelMarketDataProto(reqId: int) -> CancelMarketDataProto:
+ cancelMarketDataProto = CancelMarketDataProto()
+ if isValidIntValue(reqId): cancelMarketDataProto.reqId = reqId
+ return cancelMarketDataProto
+
+@staticmethod
+def createCancelMarketDepthProto(reqId: int, isSmartDepth: bool) -> CancelMarketDepthProto:
+ cancelMarketDepthProto = CancelMarketDepthProto()
+ if isValidIntValue(reqId): cancelMarketDepthProto.reqId = reqId
+ if isSmartDepth: cancelMarketDepthProto.isSmartDepth = isSmartDepth
+ return cancelMarketDepthProto
+
+@staticmethod
+def createAccountDataRequestProto(subscribe: bool, acctCode: str) -> AccountDataRequestProto:
+ accountDataRequestProto = AccountDataRequestProto()
+ if subscribe: accountDataRequestProto.subscribe = subscribe
+ if acctCode: accountDataRequestProto.acctCode = acctCode
+ return accountDataRequestProto
+
+@staticmethod
+def createManagedAccountsRequestProto() -> ManagedAccountsRequestProto:
+ managedAccountsRequestProto = ManagedAccountsRequestProto()
+ return managedAccountsRequestProto
+
+@staticmethod
+def createPositionsRequestProto() -> PositionsRequestProto:
+ positionsRequestProto = PositionsRequestProto()
+ return positionsRequestProto
+
+@staticmethod
+def createCancelPositionsRequestProto() -> CancelPositionsProto:
+ cancelPositionsProto = CancelPositionsProto()
+ return cancelPositionsProto
+
+@staticmethod
+def createAccountSummaryRequestProto(reqId: int, group: str, tags: str) -> AccountSummaryRequestProto:
+ accountSummaryRequestProto = AccountSummaryRequestProto()
+ if isValidIntValue(reqId): accountSummaryRequestProto.reqId = reqId
+ if group: accountSummaryRequestProto.group = group
+ if tags: accountSummaryRequestProto.tags = tags
+ return accountSummaryRequestProto
+
+@staticmethod
+def createCancelAccountSummaryRequestProto(reqId: int) -> CancelAccountSummaryProto:
+ cancelAccountSummaryProto = CancelAccountSummaryProto()
+ if isValidIntValue(reqId): cancelAccountSummaryProto.reqId = reqId
+ return cancelAccountSummaryProto
+
+@staticmethod
+def createPositionsMultiRequestProto(reqId: int, account: str, modelCode: str) -> PositionsMultiRequestProto:
+ positionsMultiRequestProto = PositionsMultiRequestProto()
+ if isValidIntValue(reqId): positionsMultiRequestProto.reqId = reqId
+ if account: positionsMultiRequestProto.account = account
+ if modelCode: positionsMultiRequestProto.modelCode = modelCode
+ return positionsMultiRequestProto
+
+@staticmethod
+def createCancelPositionsMultiRequestProto(reqId: int) -> CancelPositionsMultiProto:
+ cancelPositionsMultiProto = CancelPositionsMultiProto()
+ if isValidIntValue(reqId): cancelPositionsMultiProto.reqId = reqId
+ return cancelPositionsMultiProto
+
+@staticmethod
+def createAccountUpdatesMultiRequestProto(reqId: int, account: str, modelCode: str, ledgerAndNLV: bool) -> AccountUpdatesMultiRequestProto:
+ accountUpdatesMultiRequestProto = AccountUpdatesMultiRequestProto()
+ if isValidIntValue(reqId): accountUpdatesMultiRequestProto.reqId = reqId
+ if account: accountUpdatesMultiRequestProto.account = account
+ if modelCode: accountUpdatesMultiRequestProto.modelCode = modelCode
+ if ledgerAndNLV: accountUpdatesMultiRequestProto.ledgerAndNLV = ledgerAndNLV
+ return accountUpdatesMultiRequestProto
+
+@staticmethod
+def createCancelAccountUpdatesMultiRequestProto(reqId: int) -> CancelAccountUpdatesMultiProto:
+ cancelAccountUpdatesMultiProto = CancelAccountUpdatesMultiProto()
+ if isValidIntValue(reqId): cancelAccountUpdatesMultiProto.reqId = reqId
+ return cancelAccountUpdatesMultiProto
+
+@staticmethod
+def createHistoricalDataRequestProto(reqId: int, contract: Contract, endDateTime: str, duration: str, barSizeSetting: str, whatToShow: str, useRTH: bool, formatDate: int,
+ keepUpToDate: bool, chartOptionsList: TagValueList) -> HistoricalDataRequestProto:
+ historicalDataRequestProto = HistoricalDataRequestProto()
+ if isValidIntValue(reqId): historicalDataRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: historicalDataRequestProto.contract.CopyFrom(contractProto)
+ if endDateTime: historicalDataRequestProto.endDateTime = endDateTime
+ if duration: historicalDataRequestProto.duration = duration
+ if barSizeSetting: historicalDataRequestProto.barSizeSetting = barSizeSetting
+ if whatToShow: historicalDataRequestProto.whatToShow = whatToShow
+ if useRTH: historicalDataRequestProto.useRTH = useRTH
+ if isValidIntValue(formatDate): historicalDataRequestProto.formatDate = formatDate
+ if keepUpToDate: historicalDataRequestProto.keepUpToDate = keepUpToDate
+ fillTagValueList(chartOptionsList, historicalDataRequestProto.chartOptions)
+ return historicalDataRequestProto
+
+@staticmethod
+def createRealTimeBarsRequestProto(reqId: int, contract: Contract, barSize: int, whatToShow: str, useRTH: bool, realTimeBarsOptionsList: TagValueList) -> RealTimeBarsRequestProto:
+ realTimeBarsRequestProto = RealTimeBarsRequestProto()
+ if isValidIntValue(reqId): realTimeBarsRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: realTimeBarsRequestProto.contract.CopyFrom(contractProto)
+ if isValidIntValue(barSize): realTimeBarsRequestProto.barSize = barSize
+ if whatToShow: realTimeBarsRequestProto.whatToShow = whatToShow
+ if useRTH: realTimeBarsRequestProto.useRTH = useRTH
+ fillTagValueList(realTimeBarsOptionsList, realTimeBarsRequestProto.realTimeBarsOptions)
+ return realTimeBarsRequestProto
+
+@staticmethod
+def createHeadTimestampRequestProto(reqId: int, contract: Contract, whatToShow: str, useRTH: bool, formatDate: int) -> HeadTimestampRequestProto:
+ headTimestampRequestProto = HeadTimestampRequestProto()
+ if isValidIntValue(reqId): headTimestampRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: headTimestampRequestProto.contract.CopyFrom(contractProto)
+ if whatToShow: headTimestampRequestProto.whatToShow = whatToShow
+ if useRTH: headTimestampRequestProto.useRTH = useRTH
+ if isValidIntValue(formatDate): headTimestampRequestProto.formatDate = formatDate
+ return headTimestampRequestProto
+
+@staticmethod
+def createHistogramDataRequestProto(reqId: int, contract: Contract, useRTH: bool, timePeriod: str) -> HistogramDataRequestProto:
+ histogramDataRequestProto = HistogramDataRequestProto()
+ if isValidIntValue(reqId): histogramDataRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: histogramDataRequestProto.contract.CopyFrom(contractProto)
+ if useRTH: histogramDataRequestProto.useRTH = useRTH
+ if timePeriod: histogramDataRequestProto.timePeriod = timePeriod
+ return histogramDataRequestProto
+
+@staticmethod
+def createHistoricalTicksRequestProto(reqId: int, contract: Contract, startDateTime: str, endDateTime: str, numberOfTicks: int, whatToShow: str, useRTH: bool, ignoreSize: bool,
+ miscOptionsList: TagValueList) -> HistoricalTicksRequestProto:
+ historicalTicksRequestProto = HistoricalTicksRequestProto()
+ if isValidIntValue(reqId): historicalTicksRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: historicalTicksRequestProto.contract.CopyFrom(contractProto)
+ if startDateTime: historicalTicksRequestProto.startDateTime = startDateTime
+ if endDateTime: historicalTicksRequestProto.endDateTime = endDateTime
+ if isValidIntValue(numberOfTicks): historicalTicksRequestProto.numberOfTicks = numberOfTicks
+ if whatToShow: historicalTicksRequestProto.whatToShow = whatToShow
+ if useRTH: historicalTicksRequestProto.useRTH = useRTH
+ if ignoreSize: historicalTicksRequestProto.ignoreSize = ignoreSize
+ fillTagValueList(miscOptionsList, historicalTicksRequestProto.miscOptions)
+ return historicalTicksRequestProto
+
+@staticmethod
+def createTickByTickRequestProto(reqId: int, contract: Contract, tickType: str, numberOfTicks: int, ignoreSize: bool) -> TickByTickRequestProto:
+ tickByTickRequestProto = TickByTickRequestProto()
+ if isValidIntValue(reqId): tickByTickRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: tickByTickRequestProto.contract.CopyFrom(contractProto)
+ if tickType: tickByTickRequestProto.tickType = tickType
+ if isValidIntValue(numberOfTicks): tickByTickRequestProto.numberOfTicks = numberOfTicks
+ if ignoreSize: tickByTickRequestProto.ignoreSize = ignoreSize
+ return tickByTickRequestProto
+
+@staticmethod
+def createCancelHistoricalDataProto(reqId: int) -> CancelHistoricalDataProto:
+ cancelHistoricalDataProto = CancelHistoricalDataProto()
+ if isValidIntValue(reqId): cancelHistoricalDataProto.reqId = reqId
+ return cancelHistoricalDataProto
+
+@staticmethod
+def createCancelRealTimeBarsProto(reqId: int) -> CancelRealTimeBarsProto:
+ cancelRealTimeBarsProto = CancelRealTimeBarsProto()
+ if isValidIntValue(reqId): cancelRealTimeBarsProto.reqId = reqId
+ return cancelRealTimeBarsProto
+
+@staticmethod
+def createCancelHeadTimestampProto(reqId: int) -> CancelHeadTimestampProto:
+ cancelHeadTimestampProto = CancelHeadTimestampProto()
+ if isValidIntValue(reqId): cancelHeadTimestampProto.reqId = reqId
+ return cancelHeadTimestampProto
+
+@staticmethod
+def createCancelHistogramDataProto(reqId: int) -> CancelHistogramDataProto:
+ cancelHistogramDataProto = CancelHistogramDataProto()
+ if isValidIntValue(reqId): cancelHistogramDataProto.reqId = reqId
+ return cancelHistogramDataProto
+
+@staticmethod
+def createCancelTickByTickProto(reqId: int) -> CancelTickByTickProto:
+ cancelTickByTickProto = CancelTickByTickProto()
+ if isValidIntValue(reqId): cancelTickByTickProto.reqId = reqId
+ return cancelTickByTickProto
+
+@staticmethod
+def createNewsBulletinsRequestProto(allMessages: bool) -> NewsBulletinsRequestProto:
+ newsBulletinsRequestProto = NewsBulletinsRequestProto()
+ if (allMessages): newsBulletinsRequestProto.allMessages = allMessages
+ return newsBulletinsRequestProto
+
+@staticmethod
+def createCancelNewsBulletinsProto() -> CancelNewsBulletinsProto:
+ cancelNewsBulletinsProto = CancelNewsBulletinsProto()
+ return cancelNewsBulletinsProto
+
+@staticmethod
+def createNewsArticleRequestProto(reqId: int, providerCode: str, articleId: str, newsArticleOptionsList: TagValueList) -> NewsArticleRequestProto:
+ newsArticleRequestProto = NewsArticleRequestProto()
+ if isValidIntValue(reqId): newsArticleRequestProto.reqId = reqId
+ if providerCode: newsArticleRequestProto.providerCode = providerCode
+ if articleId: newsArticleRequestProto.articleId = articleId
+ fillTagValueList(newsArticleOptionsList, newsArticleRequestProto.newsArticleOptions)
+ return newsArticleRequestProto
+
+@staticmethod
+def createNewsProvidersRequestProto() -> NewsProvidersRequestProto:
+ newsProvidersRequestProto = NewsProvidersRequestProto()
+ return newsProvidersRequestProto
+
+@staticmethod
+def createHistoricalNewsRequestProto(reqId: int, conId: int, providerCodes: str, startDateTime: str, endDateTime: str, totalResults: int, historicalNewsOptionsList: TagValueList) -> HistoricalNewsRequestProto:
+ historicalNewsRequestProto = HistoricalNewsRequestProto()
+ if isValidIntValue(reqId): historicalNewsRequestProto.reqId = reqId
+ if isValidIntValue(conId): historicalNewsRequestProto.conId = conId
+ if providerCodes: historicalNewsRequestProto.providerCodes = providerCodes
+ if startDateTime: historicalNewsRequestProto.startDateTime = startDateTime
+ if endDateTime: historicalNewsRequestProto.endDateTime = endDateTime
+ if isValidIntValue(totalResults): historicalNewsRequestProto.totalResults = totalResults
+ fillTagValueList(historicalNewsOptionsList, historicalNewsRequestProto.historicalNewsOptions)
+ return historicalNewsRequestProto
+
+@staticmethod
+def createWshMetaDataRequestProto(reqId: int) -> WshMetaDataRequestProto:
+ wshMetaDataRequestProto = WshMetaDataRequestProto()
+ if isValidIntValue(reqId): wshMetaDataRequestProto.reqId = reqId
+ return wshMetaDataRequestProto
+
+@staticmethod
+def createCancelWshMetaDataProto(reqId: int) -> CancelWshMetaDataProto:
+ cancelWshMetaDataProto = CancelWshMetaDataProto()
+ if isValidIntValue(reqId): cancelWshMetaDataProto.reqId = reqId
+ return cancelWshMetaDataProto
+
+@staticmethod
+def createWshEventDataRequestProto(reqId: int, wshEventData: WshEventData) -> WshEventDataRequestProto:
+ wshEventDataRequestProto = WshEventDataRequestProto()
+ if isValidIntValue(reqId): wshEventDataRequestProto.reqId = reqId
+
+ if wshEventData is not None:
+ if isValidIntValue(wshEventData.conId): wshEventDataRequestProto.conId = wshEventData.conId
+ if wshEventData.filter: wshEventDataRequestProto.filter = wshEventData.filter
+ if wshEventData.fillWatchlist: wshEventDataRequestProto.fillWatchlist = wshEventData.fillWatchlist
+ if wshEventData.fillPortfolio: wshEventDataRequestProto.fillPortfolio = wshEventData.fillPortfolio
+ if wshEventData.fillCompetitors: wshEventDataRequestProto.fillCompetitors = wshEventData.fillCompetitors
+ if wshEventData.startDate: wshEventDataRequestProto.startDate = wshEventData.startDate
+ if wshEventData.endDate: wshEventDataRequestProto.endDate = wshEventData.endDate
+ if isValidIntValue(wshEventData.totalLimit): wshEventDataRequestProto.totalLimit = wshEventData.totalLimit
+
+ return wshEventDataRequestProto
+
+@staticmethod
+def createCancelWshEventDataProto(reqId: int) -> CancelWshEventDataProto:
+ cancelWshEventDataProto = CancelWshEventDataProto()
+ if isValidIntValue(reqId): cancelWshEventDataProto.reqId = reqId
+ return cancelWshEventDataProto
+
+@staticmethod
+def createScannerParametersRequestProto() -> ScannerParametersRequestProto:
+ scannerParametersRequestProto = ScannerParametersRequestProto()
+ return scannerParametersRequestProto
+
+@staticmethod
+def createScannerSubscriptionRequestProto(reqId: int, subscription: ScannerSubscription,
+ scannerSubscriptionOptionsList: TagValueList, scannerSubscriptionFilterOptionsList: TagValueList) -> ScannerSubscriptionRequestProto:
+ scannerSubscriptionRequestProto = ScannerSubscriptionRequestProto()
+ if isValidIntValue(reqId): scannerSubscriptionRequestProto.reqId = reqId
+ scannerSubscriptionProto = createScannerSubscriptionProto(subscription, scannerSubscriptionOptionsList, scannerSubscriptionFilterOptionsList)
+ if scannerSubscriptionProto is not None: scannerSubscriptionRequestProto.scannerSubscription.CopyFrom(scannerSubscriptionProto)
+ return scannerSubscriptionRequestProto
+
+@staticmethod
+def createScannerSubscriptionProto(subscription: ScannerSubscription,
+ scannerSubscriptionOptionsList: TagValueList, scannerSubscriptionFilterOptionsList: TagValueList) -> ScannerSubscriptionProto:
+ if subscription is None:
+ return None
+ scannerSubscriptionProto = ScannerSubscriptionProto()
+ if isValidIntValue(subscription.numberOfRows): scannerSubscriptionProto.numberOfRows = subscription.numberOfRows
+ if subscription.instrument: scannerSubscriptionProto.instrument = subscription.instrument
+ if subscription.locationCode: scannerSubscriptionProto.locationCode = subscription.locationCode
+ if subscription.scanCode: scannerSubscriptionProto.scanCode = subscription.scanCode
+ if isValidFloatValue(subscription.abovePrice): scannerSubscriptionProto.abovePrice = subscription.abovePrice
+ if isValidFloatValue(subscription.belowPrice): scannerSubscriptionProto.belowPrice = subscription.belowPrice
+ if isValidIntValue(subscription.aboveVolume): scannerSubscriptionProto.aboveVolume = subscription.aboveVolume
+ if isValidIntValue(subscription.averageOptionVolumeAbove): scannerSubscriptionProto.averageOptionVolumeAbove = subscription.averageOptionVolumeAbove
+ if isValidFloatValue(subscription.marketCapAbove): scannerSubscriptionProto.marketCapAbove = subscription.marketCapAbove
+ if isValidFloatValue(subscription.marketCapBelow): scannerSubscriptionProto.marketCapBelow = subscription.marketCapBelow
+ if subscription.moodyRatingAbove: scannerSubscriptionProto.moodyRatingAbove = subscription.moodyRatingAbove
+ if subscription.moodyRatingBelow: scannerSubscriptionProto.moodyRatingBelow = subscription.moodyRatingBelow
+ if subscription.spRatingAbove: scannerSubscriptionProto.spRatingAbove = subscription.spRatingAbove
+ if subscription.spRatingBelow: scannerSubscriptionProto.spRatingBelow = subscription.spRatingBelow
+ if subscription.maturityDateAbove: scannerSubscriptionProto.maturityDateAbove = subscription.maturityDateAbove
+ if subscription.maturityDateBelow: scannerSubscriptionProto.maturityDateBelow = subscription.maturityDateBelow
+ if isValidFloatValue(subscription.couponRateAbove): scannerSubscriptionProto.couponRateAbove = subscription.couponRateAbove
+ if isValidFloatValue(subscription.couponRateBelow): scannerSubscriptionProto.couponRateBelow = subscription.couponRateBelow
+ if subscription.excludeConvertible: scannerSubscriptionProto.excludeConvertible = subscription.excludeConvertible
+ if subscription.scannerSettingPairs: scannerSubscriptionProto.scannerSettingPairs = subscription.scannerSettingPairs
+ if subscription.stockTypeFilter: scannerSubscriptionProto.stockTypeFilter = subscription.stockTypeFilter
+ fillTagValueList(scannerSubscriptionOptionsList, scannerSubscriptionProto.scannerSubscriptionOptions)
+ fillTagValueList(scannerSubscriptionFilterOptionsList, scannerSubscriptionProto.scannerSubscriptionFilterOptions)
+ return scannerSubscriptionProto
+
+@staticmethod
+def createFundamentalsDataRequestProto(reqId: int, contract: Contract, reportType: str, fundamentalsDataOptionsList: TagValueList) -> FundamentalsDataRequestProto:
+ fundamentalsDataRequestProto = FundamentalsDataRequestProto()
+ if isValidIntValue(reqId): fundamentalsDataRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: fundamentalsDataRequestProto.contract.CopyFrom(contractProto)
+ if reportType: fundamentalsDataRequestProto.reportType = reportType
+ fillTagValueList(fundamentalsDataOptionsList, fundamentalsDataRequestProto.fundamentalsDataOptions)
+ return fundamentalsDataRequestProto
+
+@staticmethod
+def createPnLRequestProto(reqId: int, account: str, modelCode: str) -> PnLRequestProto:
+ pnlRequestProto = PnLRequestProto()
+ if isValidIntValue(reqId): pnlRequestProto.reqId = reqId
+ if account: pnlRequestProto.account = account
+ if modelCode: pnlRequestProto.modelCode = modelCode
+ return pnlRequestProto
+
+@staticmethod
+def createPnLSingleRequestProto(reqId: int, account: str, modelCode: str, conId: int) -> PnLSingleRequestProto:
+ pnlSingleRequestProto = PnLSingleRequestProto()
+ if isValidIntValue(reqId): pnlSingleRequestProto.reqId = reqId
+ if account: pnlSingleRequestProto.account = account
+ if modelCode: pnlSingleRequestProto.modelCode = modelCode
+ if isValidIntValue(conId): pnlSingleRequestProto.conId = conId
+ return pnlSingleRequestProto
+
+@staticmethod
+def createCancelScannerSubscriptionProto(reqId: int) -> CancelScannerSubscriptionProto:
+ cancelScannerSubscriptionProto = CancelScannerSubscriptionProto()
+ if isValidIntValue(reqId): cancelScannerSubscriptionProto.reqId = reqId
+ return cancelScannerSubscriptionProto
+
+@staticmethod
+def createCancelFundamentalsDataProto(reqId: int) -> CancelFundamentalsDataProto:
+ cancelFundamentalsDataProto = CancelFundamentalsDataProto()
+ if isValidIntValue(reqId): cancelFundamentalsDataProto.reqId = reqId
+ return cancelFundamentalsDataProto
+
+@staticmethod
+def createCancelPnLProto(reqId: int) -> CancelPnLProto:
+ cancelPnLProto = CancelPnLProto()
+ if isValidIntValue(reqId): cancelPnLProto.reqId = reqId
+ return cancelPnLProto
+
+@staticmethod
+def createCancelPnLSingleProto(reqId: int) -> CancelPnLSingleProto:
+ cancelPnLSingleProto = CancelPnLSingleProto()
+ if isValidIntValue(reqId): cancelPnLSingleProto.reqId = reqId
+ return cancelPnLSingleProto
+
+@staticmethod
+def createFARequestProto(faDataType: int) -> FARequestProto:
+ faRequestProto = FARequestProto()
+ if isValidIntValue(faDataType): faRequestProto.faDataType = faDataType
+ return faRequestProto
+
+@staticmethod
+def createFAReplaceProto(reqId: int, faDataType: int, xml: str) -> FAReplaceProto:
+ faReplaceProto = FAReplaceProto()
+ if isValidIntValue(reqId): faReplaceProto.reqId = reqId
+ if isValidIntValue(faDataType): faReplaceProto.faDataType = faDataType
+ if xml: faReplaceProto.xml = xml
+ return faReplaceProto
+
+@staticmethod
+def createExerciseOptionsRequestProto(orderId: int, contract: Contract, exerciseAction: int, exerciseQuantity: int, account: str, override: bool,
+ manualOrderTime: str, customerAccount: str, professionalCustomer: bool) -> ExerciseOptionsRequestProto:
+ exerciseOptionsRequestProto = ExerciseOptionsRequestProto()
+ if isValidIntValue(orderId): exerciseOptionsRequestProto.orderId = orderId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: exerciseOptionsRequestProto.contract.CopyFrom(contractProto)
+ if isValidIntValue(exerciseAction): exerciseOptionsRequestProto.exerciseAction = exerciseAction
+ if isValidIntValue(exerciseQuantity): exerciseOptionsRequestProto.exerciseQuantity = exerciseQuantity
+ if account: exerciseOptionsRequestProto.account = account
+ if override: exerciseOptionsRequestProto.override = override
+ if manualOrderTime: exerciseOptionsRequestProto.manualOrderTime = manualOrderTime
+ if customerAccount: exerciseOptionsRequestProto.customerAccount = customerAccount
+ if professionalCustomer: exerciseOptionsRequestProto.professionalCustomer = professionalCustomer
+ return exerciseOptionsRequestProto
+
+@staticmethod
+def createCalculateImpliedVolatilityRequestProto(reqId: int, contract: Contract, optionPrice: float, underPrice: float, impliedVolatilityOptionsList: TagValueList) -> CalculateImpliedVolatilityRequestProto:
+ calculateImpliedVolatilityRequestProto = CalculateImpliedVolatilityRequestProto()
+ if isValidIntValue(reqId): calculateImpliedVolatilityRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: calculateImpliedVolatilityRequestProto.contract.CopyFrom(contractProto)
+ if isValidFloatValue(optionPrice): calculateImpliedVolatilityRequestProto.optionPrice = optionPrice
+ if isValidFloatValue(underPrice): calculateImpliedVolatilityRequestProto.underPrice = underPrice
+ fillTagValueList(impliedVolatilityOptionsList, calculateImpliedVolatilityRequestProto.impliedVolatilityOptions)
+ return calculateImpliedVolatilityRequestProto
+
+@staticmethod
+def createCancelCalculateImpliedVolatilityProto(reqId: int) -> CancelCalculateImpliedVolatilityProto:
+ cancelCalculateImpliedVolatilityProto = CancelCalculateImpliedVolatilityProto()
+ if isValidIntValue(reqId): cancelCalculateImpliedVolatilityProto.reqId = reqId
+ return cancelCalculateImpliedVolatilityProto
+
+@staticmethod
+def createCalculateOptionPriceRequestProto(reqId: int, contract: Contract, volatility: float, underPrice: float, optionPriceOptionsList: TagValueList) -> CalculateOptionPriceRequestProto:
+ calculateOptionPriceRequestProto = CalculateOptionPriceRequestProto()
+ if isValidIntValue(reqId): calculateOptionPriceRequestProto.reqId = reqId
+ contractProto = createContractProto(contract, None)
+ if contractProto is not None: calculateOptionPriceRequestProto.contract.CopyFrom(contractProto)
+ if isValidFloatValue(volatility): calculateOptionPriceRequestProto.volatility = volatility
+ if isValidFloatValue(underPrice): calculateOptionPriceRequestProto.underPrice = underPrice
+ fillTagValueList(optionPriceOptionsList, calculateOptionPriceRequestProto.optionPriceOptions)
+ return calculateOptionPriceRequestProto
+
+@staticmethod
+def createCancelCalculateOptionPriceProto(reqId: int) -> CancelCalculateOptionPriceProto:
+ cancelCalculateOptionPriceProto = CancelCalculateOptionPriceProto()
+ if isValidIntValue(reqId): cancelCalculateOptionPriceProto.reqId = reqId
+ return cancelCalculateOptionPriceProto
+
+@staticmethod
+def createSecDefOptParamsRequestProto(reqId: int, underlyingSymbol: str, futFopExchange: str, underlyingSecType: str, underlyingConId: int) -> SecDefOptParamsRequestProto:
+ secDefOptParamsRequestProto = SecDefOptParamsRequestProto()
+ if isValidIntValue(reqId): secDefOptParamsRequestProto.reqId = reqId
+ if underlyingSymbol: secDefOptParamsRequestProto.underlyingSymbol = underlyingSymbol
+ if futFopExchange: secDefOptParamsRequestProto.futFopExchange = futFopExchange
+ if underlyingSecType: secDefOptParamsRequestProto.underlyingSecType = underlyingSecType
+ if isValidIntValue(underlyingConId): secDefOptParamsRequestProto.underlyingConId = underlyingConId
+ return secDefOptParamsRequestProto
+
+@staticmethod
+def createSoftDollarTiersRequestProto(reqId: int) -> SoftDollarTiersRequestProto:
+ softDollarTiersRequestProto = SoftDollarTiersRequestProto()
+ if isValidIntValue(reqId): softDollarTiersRequestProto.reqId = reqId
+ return softDollarTiersRequestProto
+
+@staticmethod
+def createFamilyCodesRequestProto() -> FamilyCodesRequestProto:
+ familyCodesRequestProto = FamilyCodesRequestProto()
+ return familyCodesRequestProto
+
+@staticmethod
+def createMatchingSymbolsRequestProto(reqId: int, pattern: str) -> MatchingSymbolsRequestProto:
+ matchingSymbolsRequestProto = MatchingSymbolsRequestProto()
+ if isValidIntValue(reqId): matchingSymbolsRequestProto.reqId = reqId
+ if pattern: matchingSymbolsRequestProto.pattern = pattern
+ return matchingSymbolsRequestProto
+
+@staticmethod
+def createSmartComponentsRequestProto(reqId: int, bboExchange: str) -> SmartComponentsRequestProto:
+ smartComponentsRequestProto = SmartComponentsRequestProto()
+ if isValidIntValue(reqId): smartComponentsRequestProto.reqId = reqId
+ if bboExchange: smartComponentsRequestProto.bboExchange = bboExchange
+ return smartComponentsRequestProto
+
+@staticmethod
+def createMarketRuleRequestProto(marketRuleId: int) -> MarketRuleRequestProto:
+ marketRuleRequestProto = MarketRuleRequestProto()
+ if isValidIntValue(marketRuleId): marketRuleRequestProto.marketRuleId = marketRuleId
+ return marketRuleRequestProto
+
+@staticmethod
+def createUserInfoRequestProto(reqId: int) -> UserInfoRequestProto:
+ userInfoRequestProto = UserInfoRequestProto()
+ if isValidIntValue(reqId): userInfoRequestProto.reqId = reqId
+ return userInfoRequestProto
+
+@staticmethod
+def createIdsRequestProto(numIds: int) -> IdsRequestProto:
+ idsRequestProto = IdsRequestProto()
+ if isValidIntValue(numIds): idsRequestProto.numIds = numIds
+ return idsRequestProto
+
+@staticmethod
+def createCurrentTimeRequestProto() -> CurrentTimeRequestProto:
+ currentTimeRequestProto = CurrentTimeRequestProto()
+ return currentTimeRequestProto
+
+@staticmethod
+def createCurrentTimeInMillisRequestProto() -> CurrentTimeInMillisRequestProto:
+ currentTimeInMillisRequestProto = CurrentTimeInMillisRequestProto()
+ return currentTimeInMillisRequestProto
+
+@staticmethod
+def createStartApiRequestProto(clientId: int, optionalCapabilities: str) -> StartApiRequestProto:
+ startApiRequestProto = StartApiRequestProto()
+ if isValidIntValue(clientId): startApiRequestProto.clientId = clientId
+ if optionalCapabilities: startApiRequestProto.optionalCapabilities = optionalCapabilities
+ return startApiRequestProto
+
+@staticmethod
+def createSetServerLogLevelRequestProto(logLevel: int) -> SetServerLogLevelRequestProto:
+ setServerLogLevelRequestProto = SetServerLogLevelRequestProto()
+ if isValidIntValue(logLevel): setServerLogLevelRequestProto.logLevel = logLevel
+ return setServerLogLevelRequestProto
+
+@staticmethod
+def createVerifyRequestProto(apiName: str, apiVersion: str) -> VerifyRequestProto:
+ verifyRequestProto = VerifyRequestProto()
+ if apiName: verifyRequestProto.apiName = apiName
+ if apiVersion: verifyRequestProto.apiVersion = apiVersion
+ return verifyRequestProto
+
+@staticmethod
+def createVerifyMessageRequestProto(apiData: str) -> VerifyMessageRequestProto:
+ verifyMessageRequestProto = VerifyMessageRequestProto()
+ if apiData: verifyMessageRequestProto.apiData = apiData
+ return verifyMessageRequestProto
+
+@staticmethod
+def createQueryDisplayGroupsRequestProto(reqId: int) -> QueryDisplayGroupsRequestProto:
+ queryDisplayGroupsRequestProto = QueryDisplayGroupsRequestProto()
+ if isValidIntValue(reqId): queryDisplayGroupsRequestProto.reqId = reqId
+ return queryDisplayGroupsRequestProto
+
+@staticmethod
+def createSubscribeToGroupEventsRequestProto(reqId: int, groupId: int) -> SubscribeToGroupEventsRequestProto:
+ subscribeToGroupEventsRequestProto = SubscribeToGroupEventsRequestProto()
+ if isValidIntValue(reqId): subscribeToGroupEventsRequestProto.reqId = reqId
+ if isValidIntValue(groupId): subscribeToGroupEventsRequestProto.groupId = groupId
+ return subscribeToGroupEventsRequestProto
+
+@staticmethod
+def createUpdateDisplayGroupRequestProto(reqId: int, contractInfo: str) -> UpdateDisplayGroupRequestProto:
+ updateDisplayGroupRequestProto = UpdateDisplayGroupRequestProto()
+ if isValidIntValue(reqId): updateDisplayGroupRequestProto.reqId = reqId
+ if contractInfo: updateDisplayGroupRequestProto.contractInfo = contractInfo
+ return updateDisplayGroupRequestProto
+
+@staticmethod
+def createUnsubscribeFromGroupEventsRequestProto(reqId: int) -> UnsubscribeFromGroupEventsRequestProto:
+ unsubscribeFromGroupEventsRequestProto = UnsubscribeFromGroupEventsRequestProto()
+ if isValidIntValue(reqId): unsubscribeFromGroupEventsRequestProto.reqId = reqId
+ return unsubscribeFromGroupEventsRequestProto
+
+@staticmethod
+def createMarketDepthExchangesRequestProto() -> MarketDepthExchangesRequestProto:
+ marketDepthExchangesRequestProto = MarketDepthExchangesRequestProto()
+ return marketDepthExchangesRequestProto
+
+@staticmethod
+def createCancelContractDataProto(reqId: int) -> CancelContractDataProto:
+ cancelContractDataProto = CancelContractDataProto()
+ if isValidIntValue(reqId): cancelContractDataProto.reqId = reqId
+ return cancelContractDataProto
+
+@staticmethod
+def createCancelHistoricalTicksProto(reqId: int) -> CancelHistoricalTicksProto:
+ cancelHistoricalTicksProto = CancelHistoricalTicksProto()
+ if isValidIntValue(reqId): cancelHistoricalTicksProto.reqId = reqId
+ return cancelHistoricalTicksProto
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/comm.py b/packages/ibkr/ref/source/pythonclient/ibapi/comm.py
new file mode 100644
index 00000000..becc031c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/comm.py
@@ -0,0 +1,100 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+
+This module has tools for implementing the IB low level messaging.
+"""
+
+import struct
+import logging
+import sys
+
+from ibapi.const import UNSET_INTEGER, UNSET_DOUBLE, DOUBLE_INFINITY, INFINITY_STR
+from ibapi.utils import ClientException
+from ibapi.utils import isAsciiPrintable
+from ibapi.errors import INVALID_SYMBOL
+
+logger = logging.getLogger(__name__)
+
+def make_msg_proto(msgId: int, protobufData: bytes) -> bytes:
+ """adds the length prefix"""
+ byteArray = msgId.to_bytes(4, 'big') + protobufData
+ msg = struct.pack(f"!I{len(byteArray)}s", len(byteArray), byteArray)
+ return msg
+
+def make_msg(msgId:int, useRawIntMsgId: bool, text: str) -> bytes:
+ """adds the length prefix"""
+ if useRawIntMsgId:
+ text = msgId.to_bytes(4, 'big') + str.encode(text)
+ else:
+ text = str.encode(make_field(msgId) + text)
+
+ msg = struct.pack(f"!I{len(text)}s", len(text), text)
+ return msg
+
+def make_initial_msg(text: str) -> bytes:
+ """adds the length prefix"""
+ msg = struct.pack(f"!I{len(text)}s", len(text), str.encode(text))
+ return msg
+
+
+def make_field(val) -> str:
+ """adds the NULL string terminator"""
+ if val is None:
+ raise ValueError("Cannot send None to TWS")
+
+ # if string is not empty and contains invalid symbols
+ if val is not None and type(val) == str and val and not isAsciiPrintable(val):
+ raise ClientException(
+ INVALID_SYMBOL.code(),
+ INVALID_SYMBOL.msg(),
+ val.encode(sys.stdout.encoding, errors="ignore").decode(
+ sys.stdout.encoding
+ ),
+ )
+
+ # bool type is encoded as int
+ if val is not None and type(val) == bool:
+ val = int(val)
+
+ field = str(val) + "\0"
+ return field
+
+
+def make_field_handle_empty(val) -> str:
+ if val is None:
+ raise ValueError("Cannot send None to TWS")
+
+ if UNSET_INTEGER == val or UNSET_DOUBLE == val:
+ val = ""
+
+ if DOUBLE_INFINITY == val:
+ val = INFINITY_STR
+
+ return make_field(val)
+
+
+def read_msg(buf: bytes) -> tuple:
+ """first the size prefix and then the corresponding msg payload"""
+
+ if len(buf) < 4:
+ return (0, "", buf)
+ size = struct.unpack("!I", buf[0:4])[0]
+ logger.debug("read_msg: size: %d", size)
+ if len(buf) - 4 >= size:
+ text = struct.unpack("!%ds" % size, buf[4 : 4 + size])[0]
+ return (size, text, buf[4 + size :])
+ else:
+ return (size, "", buf)
+
+
+def read_fields(buf: bytes) -> tuple:
+ if isinstance(buf, str):
+ buf = buf.encode()
+
+ """ msg payload is made of fields terminated/separated by NULL chars """
+ fields = buf.split(b"\0")
+
+ return tuple(
+ fields[0:-1]
+ ) # last one is empty; this may slow dow things though, TODO
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/commission_and_fees_report.py b/packages/ibkr/ref/source/pythonclient/ibapi/commission_and_fees_report.py
new file mode 100644
index 00000000..a67ba75a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/commission_and_fees_report.py
@@ -0,0 +1,31 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.object_implem import Object
+from ibapi.utils import intMaxString
+from ibapi.utils import floatMaxString
+
+
+class CommissionAndFeesReport(Object):
+ def __init__(self):
+ self.execId = ""
+ self.commissionAndFees = 0.0
+ self.currency = ""
+ self.realizedPNL = 0.0
+ self.yield_ = 0.0
+ self.yieldRedemptionDate = 0 # YYYYMMDD format
+
+ def __str__(self):
+ return (
+ "ExecId: %s, CommissionAndFees: %s, Currency: %s, RealizedPnL: %s, Yield: %s, YieldRedemptionDate: %s"
+ % (
+ self.execId,
+ floatMaxString(self.commissionAndFees),
+ self.currency,
+ floatMaxString(self.realizedPNL),
+ floatMaxString(self.yield_),
+ intMaxString(self.yieldRedemptionDate),
+ )
+ )
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/common.py b/packages/ibkr/ref/source/pythonclient/ibapi/common.py
new file mode 100644
index 00000000..d9ec7fac
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/common.py
@@ -0,0 +1,400 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+from ibapi.const import UNSET_INTEGER, UNSET_DECIMAL
+from ibapi.enum_implem import Enum
+from ibapi.object_implem import Object
+from ibapi.utils import floatMaxString, decimalMaxString, intMaxString
+from ibapi.message import OUT
+from ibapi.server_versions import (
+ MIN_SERVER_VER_PROTOBUF,
+ MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ MIN_SERVER_VER_PROTOBUF_CONTRACT_DATA,
+ MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3
+)
+
+TickerId = int
+OrderId = int
+TagValueList = list
+
+FaDataType = int
+FaDataTypeEnum = Enum("N/A", "GROUPS", "N/A", "ALIASES")
+
+MarketDataType = int
+MarketDataTypeEnum = Enum("N/A", "REALTIME", "FROZEN", "DELAYED", "DELAYED_FROZEN")
+
+Liquidities = int
+LiquiditiesEnum = Enum("None", "Added", "Remove", "RoudedOut")
+
+SetOfString = set
+SetOfFloat = set
+ListOfOrder = list
+ListOfFamilyCode = list
+ListOfContractDescription = list
+ListOfDepthExchanges = list
+ListOfNewsProviders = list
+SmartComponentMap = dict
+HistogramDataList = list
+ListOfPriceIncrements = list
+ListOfHistoricalTick = list
+ListOfHistoricalTickBidAsk = list
+ListOfHistoricalTickLast = list
+ListOfHistoricalSessions = list
+
+PROTOBUF_MSG_ID = 200
+PROTOBUF_MSG_IDS = {
+ OUT.REQ_EXECUTIONS : MIN_SERVER_VER_PROTOBUF,
+ OUT.PLACE_ORDER : MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ OUT.CANCEL_ORDER : MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ OUT.REQ_GLOBAL_CANCEL : MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ OUT.REQ_ALL_OPEN_ORDERS : MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ OUT.REQ_AUTO_OPEN_ORDERS : MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ OUT.REQ_OPEN_ORDERS : MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ OUT.REQ_COMPLETED_ORDERS : MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ OUT.REQ_CONTRACT_DATA : MIN_SERVER_VER_PROTOBUF_CONTRACT_DATA,
+ OUT.REQ_MKT_DATA : MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ OUT.CANCEL_MKT_DATA : MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ OUT.REQ_MKT_DEPTH : MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ OUT.CANCEL_MKT_DEPTH : MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ OUT.REQ_MARKET_DATA_TYPE : MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ OUT.REQ_ACCT_DATA : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.REQ_MANAGED_ACCTS : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.REQ_POSITIONS : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.CANCEL_POSITIONS : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.REQ_ACCOUNT_SUMMARY : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.CANCEL_ACCOUNT_SUMMARY : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.REQ_POSITIONS_MULTI : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.CANCEL_POSITIONS_MULTI : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.REQ_ACCOUNT_UPDATES_MULTI : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.CANCEL_ACCOUNT_UPDATES_MULTI : MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ OUT.REQ_HISTORICAL_DATA : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.CANCEL_HISTORICAL_DATA : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.REQ_REAL_TIME_BARS : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.CANCEL_REAL_TIME_BARS : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.REQ_HEAD_TIMESTAMP : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.CANCEL_HEAD_TIMESTAMP : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.REQ_HISTOGRAM_DATA : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.CANCEL_HISTOGRAM_DATA : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.REQ_HISTORICAL_TICKS : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.REQ_TICK_BY_TICK_DATA : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.CANCEL_TICK_BY_TICK_DATA : MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ OUT.REQ_NEWS_BULLETINS: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.CANCEL_NEWS_BULLETINS: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.REQ_NEWS_ARTICLE: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.REQ_NEWS_PROVIDERS: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.REQ_HISTORICAL_NEWS: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.REQ_WSH_META_DATA: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.CANCEL_WSH_META_DATA: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.REQ_WSH_EVENT_DATA: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.CANCEL_WSH_EVENT_DATA: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ OUT.REQ_SCANNER_PARAMETERS: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.REQ_SCANNER_SUBSCRIPTION: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.CANCEL_SCANNER_SUBSCRIPTION: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.REQ_FUNDAMENTAL_DATA: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.CANCEL_FUNDAMENTAL_DATA: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.REQ_PNL: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.CANCEL_PNL: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.REQ_PNL_SINGLE: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.CANCEL_PNL_SINGLE: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ OUT.REQ_FA: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.REPLACE_FA: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.EXERCISE_OPTIONS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.REQ_CALC_IMPLIED_VOLAT: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.CANCEL_CALC_IMPLIED_VOLAT: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.REQ_CALC_OPTION_PRICE: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.CANCEL_CALC_OPTION_PRICE: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ OUT.REQ_SEC_DEF_OPT_PARAMS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_SOFT_DOLLAR_TIERS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_FAMILY_CODES: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_MATCHING_SYMBOLS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_SMART_COMPONENTS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_MARKET_RULE: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_USER_INFO: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ OUT.REQ_IDS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.REQ_CURRENT_TIME: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.REQ_CURRENT_TIME_IN_MILLIS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.START_API: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.SET_SERVER_LOGLEVEL: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.VERIFY_REQUEST: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.VERIFY_MESSAGE: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.QUERY_DISPLAY_GROUPS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.SUBSCRIBE_TO_GROUP_EVENTS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.UPDATE_DISPLAY_GROUP: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.UNSUBSCRIBE_FROM_GROUP_EVENTS: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ OUT.REQ_MKT_DEPTH_EXCHANGES: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3
+}
+
+class BarData(Object):
+ def __init__(self):
+ self.date = ""
+ self.open = 0.0
+ self.high = 0.0
+ self.low = 0.0
+ self.close = 0.0
+ self.volume = UNSET_DECIMAL
+ self.wap = UNSET_DECIMAL
+ self.barCount = 0
+
+ def __str__(self):
+ return (
+ f"Date: {self.date}, "
+ f"Open: {floatMaxString(self.open)}, "
+ f"High: {floatMaxString(self.high)}, "
+ f"Low: {floatMaxString(self.low)}, "
+ f"Close: {floatMaxString(self.close)}, "
+ f"Volume: {decimalMaxString(self.volume)}, "
+ f"WAP: {decimalMaxString(self.wap)}, "
+ f"BarCount: {intMaxString(self.barCount)}"
+ )
+
+
+class RealTimeBar(Object):
+ def __init__(
+ self,
+ time=0,
+ endTime=-1,
+ open_=0.0,
+ high=0.0,
+ low=0.0,
+ close=0.0,
+ volume=UNSET_DECIMAL,
+ wap=UNSET_DECIMAL,
+ count=0,
+ ):
+ self.time = time
+ self.endTime = endTime
+ self.open_ = open_
+ self.high = high
+ self.low = low
+ self.close = close
+ self.volume = volume
+ self.wap = wap
+ self.count = count
+
+ def __str__(self):
+ return (
+ "Time: %s, Open: %s, High: %s, Low: %s, Close: %s, Volume: %s, WAP: %s, Count: %s"
+ % (
+ intMaxString(self.time),
+ floatMaxString(self.open_),
+ floatMaxString(self.high),
+ floatMaxString(self.low),
+ floatMaxString(self.close),
+ decimalMaxString(self.volume),
+ decimalMaxString(self.wap),
+ intMaxString(self.count),
+ )
+ )
+
+
+class HistogramData(Object):
+ def __init__(self):
+ self.price = 0.0
+ self.size = UNSET_DECIMAL
+
+ def __str__(self):
+ return "Price: %s, Size: %s" % (
+ floatMaxString(self.price),
+ decimalMaxString(self.size),
+ )
+
+
+class NewsProvider(Object):
+ def __init__(self):
+ self.code = ""
+ self.name = ""
+
+ def __str__(self):
+ return f"Code: {self.code}, Name: {self.name}"
+
+
+class DepthMktDataDescription(Object):
+ def __init__(self):
+ self.exchange = ""
+ self.secType = ""
+ self.listingExch = ""
+ self.serviceDataType = ""
+ self.aggGroup = UNSET_INTEGER
+
+ def __str__(self):
+ if self.aggGroup != UNSET_INTEGER:
+ aggGroup = self.aggGroup
+ else:
+ aggGroup = ""
+ return (
+ "Exchange: %s, SecType: %s, ListingExchange: %s, ServiceDataType: %s, AggGroup: %s, "
+ % (
+ self.exchange,
+ self.secType,
+ self.listingExch,
+ self.serviceDataType,
+ intMaxString(aggGroup),
+ )
+ )
+
+
+class SmartComponent(Object):
+ def __init__(self):
+ self.bitNumber = 0
+ self.exchange = ""
+ self.exchangeLetter = ""
+
+ def __str__(self):
+ return "BitNumber: %d, Exchange: %s, ExchangeLetter: %s" % (
+ self.bitNumber,
+ self.exchange,
+ self.exchangeLetter,
+ )
+
+
+class TickAttrib(Object):
+ def __init__(self):
+ self.canAutoExecute = False
+ self.pastLimit = False
+ self.preOpen = False
+
+ def __str__(self):
+ return "CanAutoExecute: %d, PastLimit: %d, PreOpen: %d" % (
+ self.canAutoExecute,
+ self.pastLimit,
+ self.preOpen,
+ )
+
+
+class TickAttribBidAsk(Object):
+ def __init__(self):
+ self.bidPastLow = False
+ self.askPastHigh = False
+
+ def __str__(self):
+ return "BidPastLow: %d, AskPastHigh: %d" % (self.bidPastLow, self.askPastHigh)
+
+
+class TickAttribLast(Object):
+ def __init__(self):
+ self.pastLimit = False
+ self.unreported = False
+
+ def __str__(self):
+ return "PastLimit: %d, Unreported: %d" % (self.pastLimit, self.unreported)
+
+
+class FamilyCode(Object):
+ def __init__(self):
+ self.accountID = ""
+ self.familyCodeStr = ""
+
+ def __str__(self):
+ return f"AccountId: {self.accountID}, FamilyCodeStr: {self.familyCodeStr}"
+
+
+class PriceIncrement(Object):
+ def __init__(self):
+ self.lowEdge = 0.0
+ self.increment = 0.0
+
+ def __str__(self):
+ return "LowEdge: %s, Increment: %s" % (
+ floatMaxString(self.lowEdge),
+ floatMaxString(self.increment),
+ )
+
+
+class HistoricalTick(Object):
+ def __init__(self):
+ self.time = 0
+ self.price = 0.0
+ self.size = UNSET_DECIMAL
+
+ def __str__(self):
+ return "Time: %s, Price: %s, Size: %s" % (
+ intMaxString(self.time),
+ floatMaxString(self.price),
+ decimalMaxString(self.size),
+ )
+
+
+class HistoricalTickBidAsk(Object):
+ def __init__(self):
+ self.time = 0
+ self.tickAttribBidAsk = TickAttribBidAsk()
+ self.priceBid = 0.0
+ self.priceAsk = 0.0
+ self.sizeBid = UNSET_DECIMAL
+ self.sizeAsk = UNSET_DECIMAL
+
+ def __str__(self):
+ return (
+ f"Time: {intMaxString(self.time)}, "
+ f"TickAttriBidAsk: {self.tickAttribBidAsk}, "
+ f"PriceBid: {floatMaxString(self.priceBid)}, "
+ f"PriceAsk: {floatMaxString(self.priceAsk)}, "
+ f"SizeBid: {decimalMaxString(self.sizeBid)}, "
+ f"SizeAsk: {decimalMaxString(self.sizeAsk)}"
+ )
+
+
+class HistoricalTickLast(Object):
+ def __init__(self):
+ self.time = 0
+ self.tickAttribLast = TickAttribLast()
+ self.price = 0.0
+ self.size = UNSET_DECIMAL
+ self.exchange = ""
+ self.specialConditions = ""
+
+ def __str__(self):
+ return (
+ f"Time: {intMaxString(self.time)}, "
+ f"TickAttribLast: {self.tickAttribLast}, "
+ f"Price: {floatMaxString(self.price)}, "
+ f"Size: {decimalMaxString(self.size)}, "
+ f"Exchange: {self.exchange}, "
+ f"SpecialConditions: {self.specialConditions}"
+ )
+
+
+class HistoricalSession(Object):
+ def __init__(self):
+ self.startDateTime = ""
+ self.endDateTime = ""
+ self.refDate = ""
+
+ def __str__(self):
+ return "Start: %s, End: %s, Ref Date: %s" % (
+ self.startDateTime,
+ self.endDateTime,
+ self.refDate,
+ )
+
+
+class WshEventData(Object):
+ def __init__(self):
+ self.conId = UNSET_INTEGER
+ self.filter = ""
+ self.fillWatchlist = False
+ self.fillPortfolio = False
+ self.fillCompetitors = False
+ self.startDate = ""
+ self.endDate = ""
+ self.totalLimit = UNSET_INTEGER
+
+ def __str__(self):
+ return (
+ f"WshEventData. ConId: {intMaxString(self.conId)}, "
+ f"Filter: {self.filter}, "
+ f"Fill Watchlist: {self.fillWatchlist:d}, "
+ f"Fill Portfolio: {self.fillPortfolio:d}, "
+ f"Fill Competitors: {self.fillCompetitors:d}"
+ )
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/connection.py b/packages/ibkr/ref/source/pythonclient/ibapi/connection.py
new file mode 100644
index 00000000..b53b6eac
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/connection.py
@@ -0,0 +1,126 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+"""
+Just a thin wrapper around a socket.
+It allows us to keep some other info along with it.
+"""
+
+import socket
+import threading
+import logging
+import sys
+from ibapi.errors import FAIL_CREATE_SOCK
+from ibapi.errors import CONNECT_FAIL
+from ibapi.const import NO_VALID_ID
+from ibapi.utils import currentTimeMillis
+
+# TODO: support SSL !!
+
+logger = logging.getLogger(__name__)
+
+
+class Connection:
+ def __init__(self, host, port):
+ self.host = host
+ self.port = port
+ self.socket = None
+ self.wrapper = None
+ self.lock = threading.Lock()
+
+ def connect(self):
+ try:
+ self.socket = socket.socket()
+ # TODO: list the exceptions you want to catch
+ except socket.error:
+ if self.wrapper:
+ self.wrapper.error(
+ NO_VALID_ID, currentTimeMillis(), FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()
+ )
+
+ try:
+ self.socket.connect((self.host, self.port))
+ except socket.error:
+ if self.wrapper:
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), CONNECT_FAIL.code(), CONNECT_FAIL.msg())
+
+ self.socket.settimeout(1) # non-blocking
+
+ def disconnect(self):
+ self.lock.acquire()
+ try:
+ if self.socket is not None:
+ logger.debug("disconnecting")
+ self.socket.close()
+ self.socket = None
+ logger.debug("disconnected")
+ if self.wrapper:
+ self.wrapper.connectionClosed()
+ finally:
+ self.lock.release()
+
+ def isConnected(self):
+ return self.socket is not None
+
+ def sendMsg(self, msg):
+ logger.debug("acquiring lock")
+ self.lock.acquire()
+ logger.debug("acquired lock")
+ if not self.isConnected():
+ logger.debug("sendMsg attempted while not connected, releasing lock")
+ self.lock.release()
+ return 0
+ try:
+ nSent = self.socket.send(msg)
+ except socket.error:
+ logger.debug("exception from sendMsg %s", sys.exc_info())
+ raise
+ finally:
+ logger.debug("releasing lock")
+ self.lock.release()
+ logger.debug("release lock")
+
+ logger.debug("sendMsg: sent: %d", nSent)
+
+ return nSent
+
+ def recvMsg(self):
+ if not self.isConnected():
+ logger.debug("recvMsg attempted while not connected, releasing lock")
+ return b""
+ try:
+ buf = self._recvAllMsg()
+ # receiving 0 bytes outside a timeout means the connection is either
+ # closed or broken
+ if len(buf) == 0:
+ logger.debug("socket either closed or broken, disconnecting")
+ self.disconnect()
+ except socket.timeout:
+ logger.debug("socket timeout from recvMsg %s", sys.exc_info())
+ buf = b""
+ except socket.error:
+ logger.debug("socket broken, disconnecting")
+ self.disconnect()
+ buf = b""
+ except OSError:
+ # Thrown if the socket was closed (ex: disconnected at end of script)
+ # while waiting for self.socket.recv() to timeout.
+ logger.debug("Socket is broken or closed.")
+
+ return buf
+
+ def _recvAllMsg(self):
+ cont = True
+ allbuf = b""
+
+ while cont and self.isConnected():
+ buf = self.socket.recv(4096)
+ allbuf += buf
+ logger.debug("len %d raw:%s|", len(buf), buf)
+
+ if len(buf) < 4096:
+ cont = False
+
+ return allbuf
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/const.py b/packages/ibkr/ref/source/pythonclient/ibapi/const.py
new file mode 100644
index 00000000..9801db50
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/const.py
@@ -0,0 +1,12 @@
+import math
+import sys
+from _decimal import Decimal
+
+NO_VALID_ID = -1
+MAX_MSG_LEN = 0xFFFFFF # 16Mb - 1byte
+UNSET_INTEGER = 2**31 - 1
+UNSET_DOUBLE = float(sys.float_info.max)
+UNSET_LONG = 2**63 - 1
+UNSET_DECIMAL = Decimal(2**127 - 1)
+DOUBLE_INFINITY = math.inf
+INFINITY_STR = "Infinity"
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/contract.py b/packages/ibkr/ref/source/pythonclient/ibapi/contract.py
new file mode 100644
index 00000000..1f6a7f95
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/contract.py
@@ -0,0 +1,277 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.object_implem import Object
+from ibapi.const import UNSET_DECIMAL, UNSET_DOUBLE
+
+from ibapi.utils import intMaxString
+from ibapi.utils import floatMaxString
+from ibapi.utils import decimalMaxString
+from enum import Enum
+
+"""
+SAME_POS = open/close leg value is same as combo
+OPEN_POS = open
+CLOSE_POS = close
+UNKNOWN_POS = unknown
+"""
+(SAME_POS, OPEN_POS, CLOSE_POS, UNKNOWN_POS) = range(4)
+
+
+class ComboLeg(Object):
+ def __init__(self):
+ self.conId = 0 # type: int
+ self.ratio = 0 # type: int
+ self.action = "" # BUY/SELL/SHORT
+ self.exchange = ""
+ self.openClose = 0 # type: int # LegOpenClose enum values
+ # for stock legs when doing short sale
+ self.shortSaleSlot = 0
+ self.designatedLocation = ""
+ self.exemptCode = -1
+
+ def __str__(self):
+ return ",".join(
+ (
+ intMaxString(self.conId),
+ intMaxString(self.ratio),
+ str(self.action),
+ str(self.exchange),
+ intMaxString(self.openClose),
+ intMaxString(self.shortSaleSlot),
+ str(self.designatedLocation),
+ intMaxString(self.exemptCode),
+ )
+ )
+
+
+class DeltaNeutralContract(Object):
+ def __init__(self):
+ self.conId = 0 # type: int
+ self.delta = 0.0 # type: float
+ self.price = 0.0 # type: float
+
+ def __str__(self):
+ return ",".join(
+ (str(self.conId), floatMaxString(self.delta), floatMaxString(self.price))
+ )
+
+
+class Contract(Object):
+ def __init__(self):
+ self.conId = 0
+ self.symbol = ""
+ self.secType = ""
+ self.lastTradeDateOrContractMonth = ""
+ self.lastTradeDate = ""
+ self.strike = UNSET_DOUBLE # float !!
+ self.right = ""
+ self.multiplier = ""
+ self.exchange = ""
+ self.primaryExchange = "" # pick an actual (ie non-aggregate) exchange that the contract trades on.
+ # DO NOT SET TO SMART.
+ self.currency = ""
+ self.localSymbol = ""
+ self.tradingClass = ""
+ self.includeExpired = False
+ self.secIdType = "" # CUSIP;SEDOL;ISIN;RIC
+ self.secId = ""
+ self.description = ""
+ self.issuerId = ""
+
+ # combos
+ self.comboLegsDescrip = (
+ ""
+ ) # type: str #received in open order 14 and up for all combos
+ self.comboLegs = [] # type: list[ComboLeg]
+ self.deltaNeutralContract = None
+
+ def __str__(self):
+ s = (
+ "ConId: %s, Symbol: %s, SecType: %s, LastTradeDateOrContractMonth: %s, Strike: %s, Right: %s, Multiplier: %s, Exchange: %s, PrimaryExchange: %s, "
+ "Currency: %s, LocalSymbol: %s, TradingClass: %s, IncludeExpired: %s, SecIdType: %s, SecId: %s, Description: %s, "
+ "IssuerId: %s"
+ % (
+ intMaxString(self.conId),
+ str(self.symbol),
+ str(self.secType),
+ str(self.lastTradeDateOrContractMonth),
+ floatMaxString(self.strike),
+ str(self.right),
+ str(self.multiplier),
+ str(self.exchange),
+ str(self.primaryExchange),
+ str(self.currency),
+ str(self.localSymbol),
+ str(self.tradingClass),
+ str(self.includeExpired),
+ str(self.secIdType),
+ str(self.secId),
+ str(self.description),
+ str(self.issuerId),
+ )
+ )
+ s += "Combo:" + self.comboLegsDescrip
+
+ if self.comboLegs:
+ for leg in self.comboLegs:
+ s += ";" + str(leg)
+
+ if self.deltaNeutralContract:
+ s += ";" + str(self.deltaNeutralContract)
+
+ return s
+
+
+class ContractDetails(Object):
+ def __init__(self):
+ self.contract = Contract()
+ self.marketName = ""
+ self.minTick = 0.0
+ self.orderTypes = ""
+ self.validExchanges = ""
+ self.priceMagnifier = 0
+ self.underConId = 0
+ self.longName = ""
+ self.contractMonth = ""
+ self.industry = ""
+ self.category = ""
+ self.subcategory = ""
+ self.timeZoneId = ""
+ self.tradingHours = ""
+ self.liquidHours = ""
+ self.evRule = ""
+ self.evMultiplier = 0
+ self.aggGroup = 0
+ self.underSymbol = ""
+ self.underSecType = ""
+ self.marketRuleIds = ""
+ self.secIdList = None
+ self.realExpirationDate = ""
+ self.lastTradeTime = ""
+ self.stockType = ""
+ self.minSize = UNSET_DECIMAL
+ self.sizeIncrement = UNSET_DECIMAL
+ self.suggestedSizeIncrement = UNSET_DECIMAL
+ self.minAlgoSize = UNSET_DECIMAL
+ self.lastPricePrecision = UNSET_DECIMAL
+ self.lastSizePrecision = UNSET_DECIMAL
+ # BOND values
+ self.cusip = ""
+ self.ratings = ""
+ self.descAppend = ""
+ self.bondType = ""
+ self.couponType = ""
+ self.callable = False
+ self.putable = False
+ self.coupon = 0
+ self.convertible = False
+ self.maturity = ""
+ self.issueDate = ""
+ self.nextOptionDate = ""
+ self.nextOptionType = ""
+ self.nextOptionPartial = False
+ self.notes = ""
+ # FUND values
+ self.fundName = ""
+ self.fundFamily = ""
+ self.fundType = ""
+ self.fundFrontLoad = ""
+ self.fundBackLoad = ""
+ self.fundBackLoadTimeInterval = ""
+ self.fundManagementFee = ""
+ self.fundClosed = False
+ self.fundClosedForNewInvestors = False
+ self.fundClosedForNewMoney = False
+ self.fundNotifyAmount = ""
+ self.fundMinimumInitialPurchase = ""
+ self.fundSubsequentMinimumPurchase = ""
+ self.fundBlueSkyStates = ""
+ self.fundBlueSkyTerritories = ""
+ self.fundDistributionPolicyIndicator = FundDistributionPolicyIndicator.NoneItem
+ self.fundAssetType = FundAssetType.NoneItem
+ self.ineligibilityReasonList = None
+ self.eventContract1 = ""
+ self.eventContractDescription1 = ""
+ self.eventContractDescription2 = ""
+
+ def __str__(self):
+ s = ",".join(
+ (
+ str(self.contract),
+ str(self.marketName),
+ floatMaxString(self.minTick),
+ str(self.orderTypes),
+ str(self.validExchanges),
+ intMaxString(self.priceMagnifier),
+ intMaxString(self.underConId),
+ str(self.longName),
+ str(self.contractMonth),
+ str(self.industry),
+ str(self.category),
+ str(self.subcategory),
+ str(self.timeZoneId),
+ str(self.tradingHours),
+ str(self.liquidHours),
+ str(self.evRule),
+ intMaxString(self.evMultiplier),
+ str(self.underSymbol),
+ str(self.underSecType),
+ str(self.marketRuleIds),
+ intMaxString(self.aggGroup),
+ str(self.secIdList),
+ str(self.realExpirationDate),
+ str(self.stockType),
+ str(self.cusip),
+ str(self.ratings),
+ str(self.descAppend),
+ str(self.bondType),
+ str(self.couponType),
+ str(self.callable),
+ str(self.putable),
+ str(self.coupon),
+ str(self.convertible),
+ str(self.maturity),
+ str(self.issueDate),
+ str(self.nextOptionDate),
+ str(self.nextOptionType),
+ str(self.nextOptionPartial),
+ str(self.notes),
+ decimalMaxString(self.minSize),
+ decimalMaxString(self.sizeIncrement),
+ decimalMaxString(self.suggestedSizeIncrement),
+ decimalMaxString(self.minAlgoSize),
+ decimalMaxString(self.lastPricePrecision),
+ decimalMaxString(self.lastSizePrecision),
+ str(self.ineligibilityReasonList),
+ str(self.eventContract1),
+ str(self.eventContractDescription1),
+ str(self.eventContractDescription2),
+ )
+ )
+
+ return s
+
+
+class ContractDescription(Object):
+ def __init__(self):
+ self.contract = Contract()
+ self.derivativeSecTypes = [] # type: list[str]
+
+class FundAssetType(Enum):
+ NoneItem = ("None", "None")
+ Others = ("000", "Others"),
+ MoneyMarket = ("001", "Money Market")
+ FixedIncome = ("002", "Fixed Income")
+ MultiAsset = ("003", "Multi-asset")
+ Equity = ("004", "Equity")
+ Sector = ("005", "Sector")
+ Guaranteed = ("006", "Guaranteed")
+ Alternative = ("007", "Alternative")
+
+class FundDistributionPolicyIndicator(Enum):
+ NoneItem = ("None", "None")
+ AccumulationFund = ("N", "Accumulation Fund")
+ IncomeFund = ("Y", "Income Fund")
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/decoder.py b/packages/ibkr/ref/source/pythonclient/ibapi/decoder.py
new file mode 100644
index 00000000..53cad07c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/decoder.py
@@ -0,0 +1,2971 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+from ibapi.const import NO_VALID_ID
+from ibapi.utils import getEnumTypeFromString
+from ibapi.common import PROTOBUF_MSG_ID
+
+"""
+The Decoder knows how to transform a message's payload into higher level
+IB message (eg: order info, mkt data, etc).
+It will call the corresponding method from the EWrapper so that customer's code
+(eg: class derived from EWrapper) can make further use of the data.
+"""
+
+from ibapi.message import IN
+from ibapi.wrapper import * # @UnusedWildImport
+from ibapi.contract import ContractDescription
+from ibapi.server_versions import * # @UnusedWildImport
+from ibapi.utils import * # @UnusedWildImport
+from ibapi.softdollartier import SoftDollarTier
+from ibapi.ticktype import * # @UnusedWildImport
+from ibapi.tag_value import TagValue
+from ibapi.scanner import ScanData
+from ibapi.errors import BAD_MESSAGE, UNKNOWN_ID
+from ibapi.common import * # @UnusedWildImport
+from ibapi.orderdecoder import OrderDecoder
+from ibapi.contract import FundDistributionPolicyIndicator
+from ibapi.contract import FundAssetType
+from ibapi.ineligibility_reason import IneligibilityReason
+from ibapi.decoder_utils import decodeContract, decodeOrder, decodeExecution, decodeOrderState, decodeContractDetails, setLastTradeDate
+from ibapi.decoder_utils import decodeHistoricalDataBar, decodeHistogramDataEntry, decodeHistoricalTickLast, decodeHistoricalTickBidAsk, decodeHistoricalTick
+from ibapi.decoder_utils import decodeSoftDollarTier, decodeFamilyCode, decodeSmartComponents, decodePriceIncrement, decodeDepthMarketDataDescription
+
+from ibapi.protobuf.OrderStatus_pb2 import OrderStatus as OrderStatusProto
+from ibapi.protobuf.OpenOrder_pb2 import OpenOrder as OpenOrderProto
+from ibapi.protobuf.OpenOrdersEnd_pb2 import OpenOrdersEnd as OpenOrdersEndProto
+from ibapi.protobuf.ErrorMessage_pb2 import ErrorMessage as ErrorMessageProto
+from ibapi.protobuf.ExecutionDetails_pb2 import ExecutionDetails as ExecutionDetailsProto
+from ibapi.protobuf.ExecutionDetailsEnd_pb2 import ExecutionDetailsEnd as ExecutionDetailsEndProto
+from ibapi.protobuf.CompletedOrder_pb2 import CompletedOrder as CompletedOrderProto
+from ibapi.protobuf.CompletedOrdersEnd_pb2 import CompletedOrdersEnd as CompletedOrdersEndProto
+from ibapi.protobuf.OrderBound_pb2 import OrderBound as OrderBoundProto
+from ibapi.protobuf.ContractData_pb2 import ContractData as ContractDataProto
+from ibapi.protobuf.ContractDataEnd_pb2 import ContractDataEnd as ContractDataEndProto
+from ibapi.protobuf.CompletedOrder_pb2 import CompletedOrder as CompletedOrderProto
+from ibapi.protobuf.CompletedOrdersEnd_pb2 import CompletedOrdersEnd as CompletedOrdersEndProto
+from ibapi.protobuf.OrderBound_pb2 import OrderBound as OrderBoundProto
+from ibapi.protobuf.ContractData_pb2 import ContractData as ContractDataProto
+from ibapi.protobuf.ContractDataEnd_pb2 import ContractDataEnd as ContractDataEndProto
+from ibapi.protobuf.TickPrice_pb2 import TickPrice as TickPriceProto
+from ibapi.protobuf.TickSize_pb2 import TickSize as TickSizeProto
+from ibapi.protobuf.TickOptionComputation_pb2 import TickOptionComputation as TickOptionComputationProto
+from ibapi.protobuf.TickGeneric_pb2 import TickGeneric as TickGenericProto
+from ibapi.protobuf.TickString_pb2 import TickString as TickStringProto
+from ibapi.protobuf.TickSnapshotEnd_pb2 import TickSnapshotEnd as TickSnapshotEndProto
+from ibapi.protobuf.MarketDepth_pb2 import MarketDepth as MarketDepthProto
+from ibapi.protobuf.MarketDepthL2_pb2 import MarketDepthL2 as MarketDepthL2Proto
+from ibapi.protobuf.MarketDataType_pb2 import MarketDataType as MarketDataTypeProto
+from ibapi.protobuf.TickReqParams_pb2 import TickReqParams as TickReqParamsProto
+from ibapi.protobuf.AccountValue_pb2 import AccountValue as AccountValueProto
+from ibapi.protobuf.PortfolioValue_pb2 import PortfolioValue as PortfolioValueProto
+from ibapi.protobuf.AccountUpdateTime_pb2 import AccountUpdateTime as AccountUpdateTimeProto
+from ibapi.protobuf.AccountDataEnd_pb2 import AccountDataEnd as AccountDataEndProto
+from ibapi.protobuf.ManagedAccounts_pb2 import ManagedAccounts as ManagedAccountsProto
+from ibapi.protobuf.Position_pb2 import Position as PositionProto
+from ibapi.protobuf.PositionEnd_pb2 import PositionEnd as PositionEndProto
+from ibapi.protobuf.AccountSummary_pb2 import AccountSummary as AccountSummaryProto
+from ibapi.protobuf.AccountSummaryEnd_pb2 import AccountSummaryEnd as AccountSummaryEndProto
+from ibapi.protobuf.PositionMulti_pb2 import PositionMulti as PositionMultiProto
+from ibapi.protobuf.PositionMultiEnd_pb2 import PositionMultiEnd as PositionMultiEndProto
+from ibapi.protobuf.AccountUpdateMulti_pb2 import AccountUpdateMulti as AccountUpdateMultiProto
+from ibapi.protobuf.AccountUpdateMultiEnd_pb2 import AccountUpdateMultiEnd as AccountUpdateMultiEndProto
+from ibapi.protobuf.HistoricalData_pb2 import HistoricalData as HistoricalDataProto
+from ibapi.protobuf.HistoricalDataUpdate_pb2 import HistoricalDataUpdate as HistoricalDataUpdateProto
+from ibapi.protobuf.HistoricalDataEnd_pb2 import HistoricalDataEnd as HistoricalDataEndProto
+from ibapi.protobuf.RealTimeBarTick_pb2 import RealTimeBarTick as RealTimeBarTickProto
+from ibapi.protobuf.HeadTimestamp_pb2 import HeadTimestamp as HeadTimestampProto
+from ibapi.protobuf.HistogramData_pb2 import HistogramData as HistogramDataProto
+from ibapi.protobuf.HistoricalTicks_pb2 import HistoricalTicks as HistoricalTicksProto
+from ibapi.protobuf.HistoricalTicksBidAsk_pb2 import HistoricalTicksBidAsk as HistoricalTicksBidAskProto
+from ibapi.protobuf.HistoricalTicksLast_pb2 import HistoricalTicksLast as HistoricalTicksLastProto
+from ibapi.protobuf.TickByTickData_pb2 import TickByTickData as TickByTickDataProto
+from ibapi.protobuf.NewsBulletin_pb2 import NewsBulletin as NewsBulletinProto
+from ibapi.protobuf.NewsArticle_pb2 import NewsArticle as NewsArticleProto
+from ibapi.protobuf.NewsProviders_pb2 import NewsProviders as NewsProvidersProto
+from ibapi.protobuf.HistoricalNews_pb2 import HistoricalNews as HistoricalNewsProto
+from ibapi.protobuf.HistoricalNewsEnd_pb2 import HistoricalNewsEnd as HistoricalNewsEndProto
+from ibapi.protobuf.WshMetaData_pb2 import WshMetaData as WshMetaDataProto
+from ibapi.protobuf.WshEventData_pb2 import WshEventData as WshEventDataProto
+from ibapi.protobuf.TickNews_pb2 import TickNews as TickNewsProto
+from ibapi.protobuf.ScannerParameters_pb2 import ScannerParameters as ScannerParametersProto
+from ibapi.protobuf.ScannerData_pb2 import ScannerData as ScannerDataProto
+from ibapi.protobuf.FundamentalsData_pb2 import FundamentalsData as FundamentalsDataProto
+from ibapi.protobuf.PnL_pb2 import PnL as PnLProto
+from ibapi.protobuf.PnLSingle_pb2 import PnLSingle as PnLSingleProto
+from ibapi.protobuf.ReceiveFA_pb2 import ReceiveFA as ReceiveFAProto
+from ibapi.protobuf.ReplaceFAEnd_pb2 import ReplaceFAEnd as ReplaceFAEndProto
+from ibapi.protobuf.CommissionAndFeesReport_pb2 import CommissionAndFeesReport as CommissionAndFeesReportProto
+from ibapi.protobuf.HistoricalSchedule_pb2 import HistoricalSchedule as HistoricalScheduleProto
+from ibapi.protobuf.RerouteMarketDataRequest_pb2 import RerouteMarketDataRequest as RerouteMarketDataRequestProto
+from ibapi.protobuf.RerouteMarketDepthRequest_pb2 import RerouteMarketDepthRequest as RerouteMarketDepthRequestProto
+from ibapi.protobuf.SecDefOptParameter_pb2 import SecDefOptParameter as SecDefOptParameterProto
+from ibapi.protobuf.SecDefOptParameterEnd_pb2 import SecDefOptParameterEnd as SecDefOptParameterEndProto
+from ibapi.protobuf.SoftDollarTiers_pb2 import SoftDollarTiers as SoftDollarTiersProto
+from ibapi.protobuf.FamilyCodes_pb2 import FamilyCodes as FamilyCodesProto
+from ibapi.protobuf.SymbolSamples_pb2 import SymbolSamples as SymbolSamplesProto
+from ibapi.protobuf.SmartComponents_pb2 import SmartComponents as SmartComponentsProto
+from ibapi.protobuf.MarketRule_pb2 import MarketRule as MarketRuleProto
+from ibapi.protobuf.UserInfo_pb2 import UserInfo as UserInfoProto
+from ibapi.protobuf.NextValidId_pb2 import NextValidId as NextValidIdProto
+from ibapi.protobuf.CurrentTime_pb2 import CurrentTime as CurrentTimeProto
+from ibapi.protobuf.CurrentTimeInMillis_pb2 import CurrentTimeInMillis as CurrentTimeInMillisProto
+from ibapi.protobuf.VerifyMessageApi_pb2 import VerifyMessageApi as VerifyMessageApiProto
+from ibapi.protobuf.VerifyCompleted_pb2 import VerifyCompleted as VerifyCompletedProto
+from ibapi.protobuf.DisplayGroupList_pb2 import DisplayGroupList as DisplayGroupListProto
+from ibapi.protobuf.DisplayGroupUpdated_pb2 import DisplayGroupUpdated as DisplayGroupUpdatedProto
+from ibapi.protobuf.MarketDepthExchanges_pb2 import MarketDepthExchanges as MarketDepthExchangesProto
+from ibapi.protobuf.ConfigResponse_pb2 import ConfigResponse as ConfigResponseProto
+from ibapi.protobuf.UpdateConfigResponse_pb2 import UpdateConfigResponse as UpdateConfigResponseProto
+
+logger = logging.getLogger(__name__)
+
+
+class HandleInfo(Object):
+ def __init__(self, wrap=None, proc=None):
+ self.wrapperMeth = wrap
+ self.wrapperParams = None
+ self.processMeth = proc
+ if wrap is None and proc is None:
+ raise ValueError("both wrap and proc can't be None")
+
+ def __str__(self):
+ s = f"wrap:{self.wrapperMeth} meth:{self.processMeth} prms:{self.wrapperParams}"
+ return s
+
+
+class Decoder(Object):
+ def __init__(self, wrapper, serverVersion):
+ self.wrapper = wrapper
+ self.serverVersion = serverVersion
+ self.discoverParams()
+
+ def processTickPriceMsg(self, fields):
+ decode(int, fields)
+
+ reqId = decode(int, fields)
+ tickType = decode(int, fields)
+ price = decode(float, fields)
+ size = decode(Decimal, fields) # ver 2 field
+ attrMask = decode(int, fields) # ver 3 field
+
+ attrib = TickAttrib()
+
+ attrib.canAutoExecute = attrMask == 1
+
+ if self.serverVersion >= MIN_SERVER_VER_PAST_LIMIT:
+ attrib.canAutoExecute = attrMask & 1 != 0
+ attrib.pastLimit = attrMask & 2 != 0
+ if self.serverVersion >= MIN_SERVER_VER_PRE_OPEN_BID_ASK:
+ attrib.preOpen = attrMask & 4 != 0
+
+ self.wrapper.tickPrice(reqId, tickType, price, attrib)
+
+ # process ver 2 fields
+ sizeTickType = TickTypeEnum.NOT_SET
+ if TickTypeEnum.BID == tickType:
+ sizeTickType = TickTypeEnum.BID_SIZE
+ elif TickTypeEnum.ASK == tickType:
+ sizeTickType = TickTypeEnum.ASK_SIZE
+ elif TickTypeEnum.LAST == tickType:
+ sizeTickType = TickTypeEnum.LAST_SIZE
+ elif TickTypeEnum.DELAYED_BID == tickType:
+ sizeTickType = TickTypeEnum.DELAYED_BID_SIZE
+ elif TickTypeEnum.DELAYED_ASK == tickType:
+ sizeTickType = TickTypeEnum.DELAYED_ASK_SIZE
+ elif TickTypeEnum.DELAYED_LAST == tickType:
+ sizeTickType = TickTypeEnum.DELAYED_LAST_SIZE
+
+ if sizeTickType != TickTypeEnum.NOT_SET:
+ self.wrapper.tickSize(reqId, sizeTickType, size)
+
+ def processTickPriceMsgProtoBuf(self, protobuf):
+ tickPriceProto = TickPriceProto()
+ tickPriceProto.ParseFromString(protobuf)
+
+ self.wrapper.tickPriceProtoBuf(tickPriceProto)
+
+ reqId = tickPriceProto.reqId if tickPriceProto.HasField('reqId') else NO_VALID_ID
+ tickType = tickPriceProto.tickType if tickPriceProto.HasField('tickType') else UNSET_INTEGER
+ price = tickPriceProto.price if tickPriceProto.HasField('price') else UNSET_DOUBLE
+ size = Decimal(tickPriceProto.size) if tickPriceProto.HasField('size') else UNSET_DECIMAL
+ attrMask = tickPriceProto.attrMask if tickPriceProto.HasField('attrMask') else UNSET_INTEGER
+ attrib = TickAttrib()
+ attrib.canAutoExecute = attrMask & 1 != 0
+ attrib.pastLimit = attrMask & 2 != 0
+ attrib.preOpen = attrMask & 4 != 0
+
+ self.wrapper.tickPrice(reqId, tickType, price, attrib)
+
+ sizeTickType = TickTypeEnum.NOT_SET
+ if TickTypeEnum.BID == tickType:
+ sizeTickType = TickTypeEnum.BID_SIZE
+ elif TickTypeEnum.ASK == tickType:
+ sizeTickType = TickTypeEnum.ASK_SIZE
+ elif TickTypeEnum.LAST == tickType:
+ sizeTickType = TickTypeEnum.LAST_SIZE
+ elif TickTypeEnum.DELAYED_BID == tickType:
+ sizeTickType = TickTypeEnum.DELAYED_BID_SIZE
+ elif TickTypeEnum.DELAYED_ASK == tickType:
+ sizeTickType = TickTypeEnum.DELAYED_ASK_SIZE
+ elif TickTypeEnum.DELAYED_LAST == tickType:
+ sizeTickType = TickTypeEnum.DELAYED_LAST_SIZE
+
+ if sizeTickType != TickTypeEnum.NOT_SET:
+ self.wrapper.tickSize(reqId, sizeTickType, size)
+
+ def processTickSizeMsg(self, fields):
+ decode(int, fields)
+
+ reqId = decode(int, fields)
+ sizeTickType = decode(int, fields)
+ size = decode(Decimal, fields)
+
+ if sizeTickType != TickTypeEnum.NOT_SET:
+ self.wrapper.tickSize(reqId, sizeTickType, size)
+
+ def processTickSizeMsgProtoBuf(self, protobuf):
+ tickSizeProto = TickSizeProto()
+ tickSizeProto.ParseFromString(protobuf)
+
+ self.wrapper.tickSizeProtoBuf(tickSizeProto)
+
+ reqId = tickSizeProto.reqId if tickSizeProto.HasField('reqId') else NO_VALID_ID
+ tickType = tickSizeProto.tickType if tickSizeProto.HasField('tickType') else UNSET_INTEGER
+ size = Decimal(tickSizeProto.size) if tickSizeProto.HasField('size') else UNSET_DECIMAL
+
+ if tickType != TickTypeEnum.NOT_SET:
+ self.wrapper.tickSize(reqId, tickType, size)
+
+ def processOrderStatusMsg(self, fields):
+ if self.serverVersion < MIN_SERVER_VER_MARKET_CAP_PRICE:
+ decode(int, fields)
+ orderId = decode(int, fields)
+ status = decode(str, fields)
+ filled = decode(Decimal, fields)
+ remaining = decode(Decimal, fields)
+ avgFillPrice = decode(float, fields)
+
+ permId = decode(int, fields) # ver 2 field
+ parentId = decode(int, fields) # ver 3 field
+ lastFillPrice = decode(float, fields) # ver 4 field
+ clientId = decode(int, fields) # ver 5 field
+ whyHeld = decode(str, fields) # ver 6 field
+
+ if self.serverVersion >= MIN_SERVER_VER_MARKET_CAP_PRICE:
+ mktCapPrice = decode(float, fields)
+ else:
+ mktCapPrice = None
+
+ self.wrapper.orderStatus(
+ orderId,
+ status,
+ filled,
+ remaining,
+ avgFillPrice,
+ permId,
+ parentId,
+ lastFillPrice,
+ clientId,
+ whyHeld,
+ mktCapPrice,
+ )
+
+ def processOrderStatusMsgProtoBuf(self, protobuf):
+ orderStatusProto = OrderStatusProto()
+ orderStatusProto.ParseFromString(protobuf)
+
+ self.wrapper.orderStatusProtoBuf(orderStatusProto)
+
+ orderId = orderStatusProto.orderId if orderStatusProto.HasField('orderId') else UNSET_INTEGER
+ status = orderStatusProto.status if orderStatusProto.HasField('status') else ""
+ filled = Decimal(orderStatusProto.filled) if orderStatusProto.HasField('filled') else UNSET_DECIMAL
+ remaining = Decimal(orderStatusProto.remaining) if orderStatusProto.HasField('remaining') else UNSET_DECIMAL
+ avgFillPrice = orderStatusProto.avgFillPrice if orderStatusProto.HasField('avgFillPrice') else UNSET_DOUBLE
+ permId = orderStatusProto.permId if orderStatusProto.HasField('permId') else UNSET_LONG
+ parentId = orderStatusProto.parentId if orderStatusProto.HasField('parentId') else UNSET_INTEGER
+ lastFillPrice = orderStatusProto.lastFillPrice if orderStatusProto.HasField('lastFillPrice') else UNSET_DOUBLE
+ clientId = orderStatusProto.clientId if orderStatusProto.HasField('clientId') else UNSET_INTEGER
+ whyHeld = orderStatusProto.whyHeld if orderStatusProto.HasField('whyHeld') else ""
+ mktCapPrice = orderStatusProto.mktCapPrice if orderStatusProto.HasField('mktCapPrice') else UNSET_DOUBLE
+
+ self.wrapper.orderStatus(orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice)
+
+ def processOpenOrder(self, fields):
+ order = Order()
+ contract = Contract()
+ orderState = OrderState()
+
+ if self.serverVersion < MIN_SERVER_VER_ORDER_CONTAINER:
+ version = decode(int, fields)
+ else:
+ version = self.serverVersion
+
+ OrderDecoder.__init__(
+ self, contract, order, orderState, version, self.serverVersion
+ )
+
+ # read orderId
+ OrderDecoder.decodeOrderId(self, fields)
+
+ # read contract fields
+ OrderDecoder.decodeContractFields(self, fields)
+
+ # read order fields
+ OrderDecoder.decodeAction(self, fields)
+ OrderDecoder.decodeTotalQuantity(self, fields)
+ OrderDecoder.decodeOrderType(self, fields)
+ OrderDecoder.decodeLmtPrice(self, fields)
+ OrderDecoder.decodeAuxPrice(self, fields)
+ OrderDecoder.decodeTIF(self, fields)
+ OrderDecoder.decodeOcaGroup(self, fields)
+ OrderDecoder.decodeAccount(self, fields)
+ OrderDecoder.decodeOpenClose(self, fields)
+ OrderDecoder.decodeOrigin(self, fields)
+ OrderDecoder.decodeOrderRef(self, fields)
+ OrderDecoder.decodeClientId(self, fields)
+ OrderDecoder.decodePermId(self, fields)
+ OrderDecoder.decodeOutsideRth(self, fields)
+ OrderDecoder.decodeHidden(self, fields)
+ OrderDecoder.decodeDiscretionaryAmt(self, fields)
+ OrderDecoder.decodeGoodAfterTime(self, fields)
+ OrderDecoder.skipSharesAllocation(self, fields)
+ OrderDecoder.decodeFAParams(self, fields)
+ OrderDecoder.decodeModelCode(self, fields)
+ OrderDecoder.decodeGoodTillDate(self, fields)
+ OrderDecoder.decodeRule80A(self, fields)
+ OrderDecoder.decodePercentOffset(self, fields)
+ OrderDecoder.decodeSettlingFirm(self, fields)
+ OrderDecoder.decodeShortSaleParams(self, fields)
+ OrderDecoder.decodeAuctionStrategy(self, fields)
+ OrderDecoder.decodeBoxOrderParams(self, fields)
+ OrderDecoder.decodePegToStkOrVolOrderParams(self, fields)
+ OrderDecoder.decodeDisplaySize(self, fields)
+ OrderDecoder.decodeBlockOrder(self, fields)
+ OrderDecoder.decodeSweepToFill(self, fields)
+ OrderDecoder.decodeAllOrNone(self, fields)
+ OrderDecoder.decodeMinQty(self, fields)
+ OrderDecoder.decodeOcaType(self, fields)
+ OrderDecoder.skipETradeOnly(self, fields)
+ OrderDecoder.skipFirmQuoteOnly(self, fields)
+ OrderDecoder.skipNbboPriceCap(self, fields)
+ OrderDecoder.decodeParentId(self, fields)
+ OrderDecoder.decodeTriggerMethod(self, fields)
+ OrderDecoder.decodeVolOrderParams(self, fields, True)
+ OrderDecoder.decodeTrailParams(self, fields)
+ OrderDecoder.decodeBasisPoints(self, fields)
+ OrderDecoder.decodeComboLegs(self, fields)
+ OrderDecoder.decodeSmartComboRoutingParams(self, fields)
+ OrderDecoder.decodeScaleOrderParams(self, fields)
+ OrderDecoder.decodeHedgeParams(self, fields)
+ OrderDecoder.decodeOptOutSmartRouting(self, fields)
+ OrderDecoder.decodeClearingParams(self, fields)
+ OrderDecoder.decodeNotHeld(self, fields)
+ OrderDecoder.decodeDeltaNeutral(self, fields)
+ OrderDecoder.decodeAlgoParams(self, fields)
+ OrderDecoder.decodeSolicited(self, fields)
+ OrderDecoder.decodeWhatIfInfoAndCommissionAndFees(self, fields)
+ OrderDecoder.decodeVolRandomizeFlags(self, fields)
+ OrderDecoder.decodePegToBenchParams(self, fields)
+ OrderDecoder.decodeConditions(self, fields)
+ OrderDecoder.decodeAdjustedOrderParams(self, fields)
+ OrderDecoder.decodeSoftDollarTier(self, fields)
+ OrderDecoder.decodeCashQty(self, fields)
+ OrderDecoder.decodeDontUseAutoPriceForHedge(self, fields)
+ OrderDecoder.decodeIsOmsContainers(self, fields)
+ OrderDecoder.decodeDiscretionaryUpToLimitPrice(self, fields)
+ OrderDecoder.decodeUsePriceMgmtAlgo(self, fields)
+ OrderDecoder.decodeDuration(self, fields)
+ OrderDecoder.decodePostToAts(self, fields)
+ OrderDecoder.decodeAutoCancelParent(
+ self, fields, MIN_SERVER_VER_AUTO_CANCEL_PARENT
+ )
+ OrderDecoder.decodePegBestPegMidOrderAttributes(self, fields)
+ OrderDecoder.decodeCustomerAccount(self, fields)
+ OrderDecoder.decodeProfessionalCustomer(self, fields)
+ OrderDecoder.decodeBondAccruedInterest(self, fields)
+ OrderDecoder.decodeIncludeOvernight(self, fields)
+ OrderDecoder.decodeCMETaggingFields(self, fields)
+ OrderDecoder.decodeSubmitter(self, fields)
+ OrderDecoder.decodeImbalanceOnly(
+ self, fields, MIN_SERVER_VER_IMBALANCE_ONLY
+ )
+
+ self.wrapper.openOrder(order.orderId, contract, order, orderState)
+
+ def processOpenOrderMsgProtoBuf(self, protobuf):
+ openOrderProto = OpenOrderProto()
+ openOrderProto.ParseFromString(protobuf)
+
+ self.wrapper.openOrderProtoBuf(openOrderProto)
+
+ orderId = openOrderProto.orderId if openOrderProto.HasField('orderId') else 0
+
+ # decode contract fields
+ if not openOrderProto.HasField('contract'):
+ return
+ contract = decodeContract(openOrderProto.contract)
+
+ # decode order fields
+ if not openOrderProto.HasField('order'):
+ return
+ order = decodeOrder(orderId, openOrderProto.contract, openOrderProto.order)
+
+ # decode order state fields
+ if not openOrderProto.HasField('orderState'):
+ return
+ orderState = decodeOrderState(openOrderProto.orderState)
+
+ self.wrapper.openOrder(orderId, contract, order, orderState);
+
+ def processOpenOrdersEndMsgProtoBuf(self, protobuf):
+ openOrdersEndProto = OpenOrdersEndProto()
+ openOrdersEndProto.ParseFromString(protobuf)
+
+ self.wrapper.openOrdersEndProtoBuf(openOrdersEndProto)
+
+ self.wrapper.openOrderEnd()
+
+ def processPortfolioValueMsg(self, fields):
+ version = decode(int, fields)
+
+ # read contract fields
+ contract = Contract()
+ contract.conId = decode(int, fields) # ver 6 field
+ contract.symbol = decode(str, fields)
+ contract.secType = decode(str, fields)
+ contract.lastTradeDateOrContractMonth = decode(str, fields)
+ contract.strike = decode(float, fields)
+ contract.right = decode(str, fields)
+
+ if version >= 7:
+ contract.multiplier = decode(str, fields)
+ contract.primaryExchange = decode(str, fields)
+
+ contract.currency = decode(str, fields)
+ contract.localSymbol = decode(str, fields) # ver 2 field
+ if version >= 8:
+ contract.tradingClass = decode(str, fields)
+
+ position = decode(Decimal, fields)
+
+ marketPrice = decode(float, fields)
+ marketValue = decode(float, fields)
+ averageCost = decode(float, fields) # ver 3 field
+ unrealizedPNL = decode(float, fields) # ver 3 field
+ realizedPNL = decode(float, fields) # ver 3 field
+
+ accountName = decode(str, fields) # ver 4 field
+
+ if version == 6 and self.serverVersion == 39:
+ contract.primaryExchange = decode(str, fields)
+
+ self.wrapper.updatePortfolio(
+ contract,
+ position,
+ marketPrice,
+ marketValue,
+ averageCost,
+ unrealizedPNL,
+ realizedPNL,
+ accountName,
+ )
+
+ def processPortfolioValueMsgProtoBuf(self, protobuf):
+ portfolioValueProto = PortfolioValueProto()
+ portfolioValueProto.ParseFromString(protobuf)
+
+ self.wrapper.updatePortfolioProtoBuf(portfolioValueProto)
+
+ # decode contract fields
+ if not portfolioValueProto.HasField('contract'):
+ return
+ contract = decodeContract(portfolioValueProto.contract)
+
+ position = Decimal(portfolioValueProto.position) if portfolioValueProto.HasField('position') else UNSET_DECIMAL
+ marketPrice = portfolioValueProto.marketPrice if portfolioValueProto.HasField('marketPrice') else 0
+ marketValue = portfolioValueProto.marketValue if portfolioValueProto.HasField('marketValue') else 0
+ averageCost = portfolioValueProto.averageCost if portfolioValueProto.HasField('averageCost') else 0
+ unrealizedPNL = portfolioValueProto.unrealizedPNL if portfolioValueProto.HasField('unrealizedPNL') else 0
+ realizedPNL = portfolioValueProto.realizedPNL if portfolioValueProto.HasField('realizedPNL') else 0
+ accountName = portfolioValueProto.accountName if portfolioValueProto.HasField('accountName') else ""
+
+ self.wrapper.updatePortfolio(contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName)
+
+ def processContractDataMsg(self, fields):
+ version = 8
+ if self.serverVersion < MIN_SERVER_VER_SIZE_RULES:
+ version = decode(int, fields)
+
+ reqId = -1
+ if version >= 3:
+ reqId = decode(int, fields)
+
+ contract = ContractDetails()
+ contract.contract.symbol = decode(str, fields)
+ contract.contract.secType = decode(str, fields)
+ self.readLastTradeDate(fields, contract, False)
+ if self.serverVersion >= MIN_SERVER_VER_LAST_TRADE_DATE:
+ contract.contract.lastTradeDate = decode(str, fields)
+ contract.contract.strike = decode(float, fields)
+ contract.contract.right = decode(str, fields)
+ contract.contract.exchange = decode(str, fields)
+ contract.contract.currency = decode(str, fields)
+ contract.contract.localSymbol = decode(str, fields)
+ contract.marketName = decode(str, fields)
+ contract.contract.tradingClass = decode(str, fields)
+ contract.contract.conId = decode(int, fields)
+ contract.minTick = decode(float, fields)
+ if (
+ self.serverVersion >= MIN_SERVER_VER_MD_SIZE_MULTIPLIER
+ and self.serverVersion < MIN_SERVER_VER_SIZE_RULES
+ ):
+ decode(int, fields) # mdSizeMultiplier - not used anymore
+ contract.contract.multiplier = decode(str, fields)
+ contract.orderTypes = decode(str, fields)
+ contract.validExchanges = decode(str, fields)
+ contract.priceMagnifier = decode(int, fields) # ver 2 field
+ if version >= 4:
+ contract.underConId = decode(int, fields)
+ if version >= 5:
+ contract.longName = (
+ decode(str, fields).encode().decode("unicode-escape")
+ if self.serverVersion >= MIN_SERVER_VER_ENCODE_MSG_ASCII7
+ else decode(str, fields)
+ )
+ contract.contract.primaryExchange = decode(str, fields)
+ if version >= 6:
+ contract.contractMonth = decode(str, fields)
+ contract.industry = decode(str, fields)
+ contract.category = decode(str, fields)
+ contract.subcategory = decode(str, fields)
+ contract.timeZoneId = decode(str, fields)
+ contract.tradingHours = decode(str, fields)
+ contract.liquidHours = decode(str, fields)
+ if version >= 8:
+ contract.evRule = decode(str, fields)
+ contract.evMultiplier = decode(int, fields)
+ if version >= 7:
+ secIdListCount = decode(int, fields)
+ if secIdListCount > 0:
+ contract.secIdList = []
+ for _ in range(secIdListCount):
+ tagValue = TagValue()
+ tagValue.tag = decode(str, fields)
+ tagValue.value = decode(str, fields)
+ contract.secIdList.append(tagValue)
+
+ if self.serverVersion >= MIN_SERVER_VER_AGG_GROUP:
+ contract.aggGroup = decode(int, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_UNDERLYING_INFO:
+ contract.underSymbol = decode(str, fields)
+ contract.underSecType = decode(str, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_MARKET_RULES:
+ contract.marketRuleIds = decode(str, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_REAL_EXPIRATION_DATE:
+ contract.realExpirationDate = decode(str, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_STOCK_TYPE:
+ contract.stockType = decode(str, fields)
+
+ if (
+ self.serverVersion >= MIN_SERVER_VER_FRACTIONAL_SIZE_SUPPORT
+ and self.serverVersion < MIN_SERVER_VER_SIZE_RULES
+ ):
+ decode(Decimal, fields) # sizeMinTick - not used anymore
+
+ if self.serverVersion >= MIN_SERVER_VER_SIZE_RULES:
+ contract.minSize = decode(Decimal, fields)
+ contract.sizeIncrement = decode(Decimal, fields)
+ contract.suggestedSizeIncrement = decode(Decimal, fields)
+
+ if (
+ self.serverVersion >= MIN_SERVER_VER_FUND_DATA_FIELDS
+ and contract.contract.secType == "FUND"
+ ):
+ contract.fundName = decode(str, fields)
+ contract.fundFamily = decode(str, fields)
+ contract.fundType = decode(str, fields)
+ contract.fundFrontLoad = decode(str, fields)
+ contract.fundBackLoad = decode(str, fields)
+ contract.fundBackLoadTimeInterval = decode(str, fields)
+ contract.fundManagementFee = decode(str, fields)
+ contract.fundClosed = decode(bool, fields)
+ contract.fundClosedForNewInvestors = decode(bool, fields)
+ contract.fundClosedForNewMoney = decode(bool, fields)
+ contract.fundNotifyAmount = decode(str, fields)
+ contract.fundMinimumInitialPurchase = decode(str, fields)
+ contract.fundSubsequentMinimumPurchase = decode(str, fields)
+ contract.fundBlueSkyStates = decode(str, fields)
+ contract.fundBlueSkyTerritories = decode(str, fields)
+ contract.fundDistributionPolicyIndicator = getEnumTypeFromString(FundDistributionPolicyIndicator, decode(str, fields))
+ contract.fundAssetType = getEnumTypeFromString(FundAssetType, decode(str, fields))
+
+ if self.serverVersion >= MIN_SERVER_VER_INELIGIBILITY_REASONS:
+ ineligibilityReasonListCount = decode(int, fields)
+ if ineligibilityReasonListCount > 0:
+ contract.ineligibilityReasonList = []
+ for _ in range(ineligibilityReasonListCount):
+ ineligibilityReason = IneligibilityReason()
+ ineligibilityReason.id_ = decode(str, fields)
+ ineligibilityReason.description = decode(str, fields)
+ contract.ineligibilityReasonList.append(ineligibilityReason)
+
+ self.wrapper.contractDetails(reqId, contract)
+
+ def processContractDataMsgProtoBuf(self, protobuf):
+ contractDataProto = ContractDataProto()
+ contractDataProto.ParseFromString(protobuf)
+
+ self.wrapper.contractDataProtoBuf(contractDataProto)
+
+ reqId = contractDataProto.reqId if contractDataProto.HasField('reqId') else NO_VALID_ID
+
+ # decode contract details fields
+ if not contractDataProto.HasField('contract') or not contractDataProto.HasField('contractDetails'):
+ return
+ contractDetails = decodeContractDetails(contractDataProto.contract, contractDataProto.contractDetails, False)
+
+ self.wrapper.contractDetails(reqId, contractDetails)
+
+ def processBondContractDataMsg(self, fields):
+ version = 6
+ if self.serverVersion < MIN_SERVER_VER_SIZE_RULES:
+ version = decode(int, fields)
+
+ reqId = -1
+ if version >= 3:
+ reqId = decode(int, fields)
+
+ contract = ContractDetails()
+ contract.contract.symbol = decode(str, fields)
+ contract.contract.secType = decode(str, fields)
+ contract.cusip = decode(str, fields)
+ contract.coupon = decode(float, fields)
+ self.readLastTradeDate(fields, contract, True)
+ contract.issueDate = decode(str, fields)
+ contract.ratings = decode(str, fields)
+ contract.bondType = decode(str, fields)
+ contract.couponType = decode(str, fields)
+ contract.convertible = decode(bool, fields)
+ contract.callable = decode(bool, fields)
+ contract.putable = decode(bool, fields)
+ contract.descAppend = decode(str, fields)
+ contract.contract.exchange = decode(str, fields)
+ contract.contract.currency = decode(str, fields)
+ contract.marketName = decode(str, fields)
+ contract.contract.tradingClass = decode(str, fields)
+ contract.contract.conId = decode(int, fields)
+ contract.minTick = decode(float, fields)
+ if (
+ self.serverVersion >= MIN_SERVER_VER_MD_SIZE_MULTIPLIER
+ and self.serverVersion < MIN_SERVER_VER_SIZE_RULES
+ ):
+ decode(int, fields) # mdSizeMultiplier - not used anymore
+ contract.orderTypes = decode(str, fields)
+ contract.validExchanges = decode(str, fields)
+ contract.nextOptionDate = decode(str, fields) # ver 2 field
+ contract.nextOptionType = decode(str, fields) # ver 2 field
+ contract.nextOptionPartial = decode(bool, fields) # ver 2 field
+ contract.notes = decode(str, fields) # ver 2 field
+ if version >= 4:
+ contract.longName = decode(str, fields)
+ if self.serverVersion >= MIN_SERVER_VER_BOND_TRADING_HOURS:
+ contract.timeZoneId = decode(str, fields)
+ contract.tradingHours = decode(str, fields)
+ contract.liquidHours = decode(str, fields)
+ if version >= 6:
+ contract.evRule = decode(str, fields)
+ contract.evMultiplier = decode(int, fields)
+ if version >= 5:
+ secIdListCount = decode(int, fields)
+ if secIdListCount > 0:
+ contract.secIdList = []
+ for _ in range(secIdListCount):
+ tagValue = TagValue()
+ tagValue.tag = decode(str, fields)
+ tagValue.value = decode(str, fields)
+ contract.secIdList.append(tagValue)
+
+ if self.serverVersion >= MIN_SERVER_VER_AGG_GROUP:
+ contract.aggGroup = decode(int, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_MARKET_RULES:
+ contract.marketRuleIds = decode(str, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_SIZE_RULES:
+ contract.minSize = decode(Decimal, fields)
+ contract.sizeIncrement = decode(Decimal, fields)
+ contract.suggestedSizeIncrement = decode(Decimal, fields)
+
+ self.wrapper.bondContractDetails(reqId, contract)
+
+ def processBondContractDataMsgProtoBuf(self, protobuf):
+ contractDataProto = ContractDataProto()
+ contractDataProto.ParseFromString(protobuf)
+
+ self.wrapper.bondContractDataProtoBuf(contractDataProto)
+
+ reqId = contractDataProto.reqId if contractDataProto.HasField('reqId') else NO_VALID_ID
+
+ # decode contract details fields
+ if not contractDataProto.HasField('contract') or not contractDataProto.HasField('contractDetails'):
+ return
+ contractDetails = decodeContractDetails(contractDataProto.contract, contractDataProto.contractDetails, True)
+
+ self.wrapper.bondContractDetails(reqId, contractDetails)
+
+ def processContractDataEndMsgProtoBuf(self, protobuf):
+ contractDataEndProto = ContractDataEndProto()
+ contractDataEndProto.ParseFromString(protobuf)
+
+ self.wrapper.contractDataEndProtoBuf(contractDataEndProto)
+
+ reqId = contractDataEndProto.reqId if contractDataEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.contractDetailsEnd(reqId)
+
+ def processScannerDataMsg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+
+ numberOfElements = decode(int, fields)
+
+ for _ in range(numberOfElements):
+ data = ScanData()
+ data.contract = ContractDetails()
+
+ data.rank = decode(int, fields)
+ data.contract.contract.conId = decode(int, fields) # ver 3 field
+ data.contract.contract.symbol = decode(str, fields)
+ data.contract.contract.secType = decode(str, fields)
+ data.contract.contract.lastTradeDateOrContractMonth = decode(str, fields)
+ data.contract.contract.strike = decode(float, fields)
+ data.contract.contract.right = decode(str, fields)
+ data.contract.contract.exchange = decode(str, fields)
+ data.contract.contract.currency = decode(str, fields)
+ data.contract.contract.localSymbol = decode(str, fields)
+ data.contract.marketName = decode(str, fields)
+ data.contract.contract.tradingClass = decode(str, fields)
+ data.distance = decode(str, fields)
+ data.benchmark = decode(str, fields)
+ data.projection = decode(str, fields)
+ data.legsStr = decode(str, fields)
+ self.wrapper.scannerData(
+ reqId,
+ data.rank,
+ data.contract,
+ data.distance,
+ data.benchmark,
+ data.projection,
+ data.legsStr,
+ )
+
+ self.wrapper.scannerDataEnd(reqId)
+
+ def processScannerDataMsgProtoBuf(self, protobuf):
+ scannerDataProto = ScannerDataProto()
+ scannerDataProto.ParseFromString(protobuf)
+
+ self.wrapper.scannerDataProtoBuf(scannerDataProto)
+
+ reqId = scannerDataProto.reqId if scannerDataProto.HasField('reqId') else NO_VALID_ID
+
+ if scannerDataProto.scannerDataElement:
+ for element in scannerDataProto.scannerDataElement:
+ rank = element.rank if element.HasField('rank') else 0
+
+ # Set contract details
+ contractDetails = ContractDetails()
+ if element.HasField('contract'):
+ contract = decodeContract(element.contract)
+ contractDetails.contract = contract
+ contractDetails.marketName = element.marketName if element.HasField('marketName') else ""
+
+ distance = element.distance if element.HasField('distance') else ""
+ benchmark = element.benchmark if element.HasField('benchmark') else ""
+ projection = element.projection if element.HasField('projection') else ""
+ comboKey = element.comboKey if element.HasField('comboKey') else ""
+
+ self.wrapper.scannerData(reqId, rank, contractDetails, distance, benchmark, projection, comboKey)
+
+ self.wrapper.scannerDataEnd(reqId)
+
+ def processExecutionDataMsg(self, fields):
+ version = self.serverVersion
+
+ if self.serverVersion < MIN_SERVER_VER_LAST_LIQUIDITY:
+ version = decode(int, fields)
+
+ reqId = -1
+ if version >= 7:
+ reqId = decode(int, fields)
+
+ orderId = decode(int, fields)
+
+ # decode contract fields
+ contract = Contract()
+ contract.conId = decode(int, fields) # ver 5 field
+ contract.symbol = decode(str, fields)
+ contract.secType = decode(str, fields)
+ contract.lastTradeDateOrContractMonth = decode(str, fields)
+ contract.strike = decode(float, fields)
+ contract.right = decode(str, fields)
+ if version >= 9:
+ contract.multiplier = decode(str, fields)
+ contract.exchange = decode(str, fields)
+ contract.currency = decode(str, fields)
+ contract.localSymbol = decode(str, fields)
+ if version >= 10:
+ contract.tradingClass = decode(str, fields)
+
+ # decode execution fields
+ execution = Execution()
+ execution.orderId = orderId
+ execution.execId = decode(str, fields)
+ execution.time = decode(str, fields)
+ execution.acctNumber = decode(str, fields)
+ execution.exchange = decode(str, fields)
+ execution.side = decode(str, fields)
+ execution.shares = decode(Decimal, fields)
+ execution.price = decode(float, fields)
+ execution.permId = decode(int, fields) # ver 2 field
+ execution.clientId = decode(int, fields) # ver 3 field
+ execution.liquidation = decode(int, fields) # ver 4 field
+
+ if version >= 6:
+ execution.cumQty = decode(Decimal, fields)
+ execution.avgPrice = decode(float, fields)
+
+ if version >= 8:
+ execution.orderRef = decode(str, fields)
+
+ if version >= 9:
+ execution.evRule = decode(str, fields)
+ execution.evMultiplier = decode(float, fields)
+ if self.serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT:
+ execution.modelCode = decode(str, fields)
+ if self.serverVersion >= MIN_SERVER_VER_LAST_LIQUIDITY:
+ execution.lastLiquidity = decode(int, fields)
+ if self.serverVersion >= MIN_SERVER_VER_PENDING_PRICE_REVISION:
+ execution.pendingPriceRevision = decode(bool, fields)
+ if self.serverVersion >= MIN_SERVER_VER_SUBMITTER:
+ execution.submitter = decode(str, fields)
+
+ self.wrapper.execDetails(reqId, contract, execution)
+
+ def processExecutionDataEndMsgProtoBuf(self, protobuf):
+ executionDetailsEndProto = ExecutionDetailsEndProto()
+ executionDetailsEndProto.ParseFromString(protobuf)
+
+ self.wrapper.executionDetailsEndProtoBuf(executionDetailsEndProto)
+
+ reqId = executionDetailsEndProto.reqId if executionDetailsEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.execDetailsEnd(reqId)
+
+ def processExecutionDataMsgProtoBuf(self, protobuf):
+ executionDetailsProto = ExecutionDetailsProto()
+ executionDetailsProto.ParseFromString(protobuf)
+
+ self.wrapper.executionDetailsProtoBuf(executionDetailsProto)
+
+ reqId = executionDetailsProto.reqId if executionDetailsProto.HasField('reqId') else NO_VALID_ID
+
+ # decode contract fields
+ if not executionDetailsProto.HasField('contract'):
+ return
+ contract = decodeContract(executionDetailsProto.contract)
+
+ # decode execution fields
+ if not executionDetailsProto.HasField('execution'):
+ return
+ execution = decodeExecution(executionDetailsProto.execution)
+
+ self.wrapper.execDetails(reqId, contract, execution)
+
+ def processHistoricalDataMsg(self, fields):
+ if self.serverVersion < MIN_SERVER_VER_SYNT_REALTIME_BARS:
+ decode(int, fields)
+
+ reqId = decode(int, fields)
+
+ if self.serverVersion < MIN_SERVER_VER_HISTORICAL_DATA_END:
+ startDateStr = decode(str, fields) # ver 2 field
+ endDateStr = decode(str, fields) # ver 2 field
+
+ itemCount = decode(int, fields)
+
+ for _ in range(itemCount):
+ bar = BarData()
+ bar.date = decode(str, fields)
+ bar.open = decode(float, fields)
+ bar.high = decode(float, fields)
+ bar.low = decode(float, fields)
+ bar.close = decode(float, fields)
+ bar.volume = decode(Decimal, fields)
+ bar.wap = decode(Decimal, fields)
+
+ if self.serverVersion < MIN_SERVER_VER_SYNT_REALTIME_BARS:
+ decode(str, fields)
+
+ bar.barCount = decode(int, fields) # ver 3 field
+
+ self.wrapper.historicalData(reqId, bar)
+
+ if self.serverVersion < MIN_SERVER_VER_HISTORICAL_DATA_END:
+ # send end of dataset marker
+ self.wrapper.historicalDataEnd(reqId, startDateStr, endDateStr)
+
+ def processHistoricalDataMsgProtoBuf(self, protobuf):
+ historicalDataProto = HistoricalDataProto()
+ historicalDataProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalDataProtoBuf(historicalDataProto)
+
+ reqId = historicalDataProto.reqId if historicalDataProto.HasField('reqId') else NO_VALID_ID
+
+ if not historicalDataProto.historicalDataBars:
+ return
+
+ for historicalDataBarProto in historicalDataProto.historicalDataBars:
+ bar = decodeHistoricalDataBar(historicalDataBarProto)
+ self.wrapper.historicalData(reqId, bar)
+
+ def processHistoricalDataEndMsg(self, fields):
+ reqId = decode(int, fields)
+ startDateStr = decode(str, fields)
+ endDateStr = decode(str, fields)
+
+ self.wrapper.historicalDataEnd(reqId, startDateStr, endDateStr)
+
+ def processHistoricalDataEndMsgProtoBuf(self, protobuf):
+ historicalDataEndProto = HistoricalDataEndProto()
+ historicalDataEndProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalDataEndProtoBuf(historicalDataEndProto)
+
+ reqId = historicalDataEndProto.reqId if historicalDataEndProto.HasField('reqId') else NO_VALID_ID
+ startDateStr = historicalDataEndProto.startDateStr if historicalDataEndProto.HasField('startDateStr') else ""
+ endDateStr = historicalDataEndProto.endDateStr if historicalDataEndProto.HasField('endDateStr') else ""
+
+ self.wrapper.historicalDataEnd(reqId, startDateStr, endDateStr)
+
+ def processHistoricalDataUpdateMsg(self, fields):
+ reqId = decode(int, fields)
+ bar = BarData()
+ bar.barCount = decode(int, fields)
+ bar.date = decode(str, fields)
+ bar.open = decode(float, fields)
+ bar.close = decode(float, fields)
+ bar.high = decode(float, fields)
+ bar.low = decode(float, fields)
+ bar.wap = decode(Decimal, fields)
+ bar.volume = decode(Decimal, fields)
+ self.wrapper.historicalDataUpdate(reqId, bar)
+
+ def processHistoricalDataUpdateMsgProtoBuf(self, protobuf):
+ historicalDataUpdateProto = HistoricalDataUpdateProto()
+ historicalDataUpdateProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalDataUpdateProtoBuf(historicalDataUpdateProto)
+
+ reqId = historicalDataUpdateProto.reqId if historicalDataUpdateProto.HasField('reqId') else NO_VALID_ID
+
+ if not historicalDataUpdateProto.HasField('historicalDataBar'):
+ return
+
+ bar = decodeHistoricalDataBar(historicalDataUpdateProto.historicalDataBar)
+ self.wrapper.historicalDataUpdate(reqId, bar)
+
+ def processRealTimeBarMsg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+
+ bar = RealTimeBar()
+ bar.time = decode(int, fields)
+ bar.open = decode(float, fields)
+ bar.high = decode(float, fields)
+ bar.low = decode(float, fields)
+ bar.close = decode(float, fields)
+ bar.volume = decode(Decimal, fields)
+ bar.wap = decode(Decimal, fields)
+ bar.count = decode(int, fields)
+
+ self.wrapper.realtimeBar(
+ reqId,
+ bar.time,
+ bar.open,
+ bar.high,
+ bar.low,
+ bar.close,
+ bar.volume,
+ bar.wap,
+ bar.count,
+ )
+
+ def processRealTimeBarMsgProtoBuf(self, protobuf):
+ realTimeBarTickProto = RealTimeBarTickProto()
+ realTimeBarTickProto.ParseFromString(protobuf)
+
+ self.wrapper.realTimeBarTickProtoBuf(realTimeBarTickProto)
+
+ reqId = realTimeBarTickProto.reqId if realTimeBarTickProto.HasField('reqId') else NO_VALID_ID
+ time = realTimeBarTickProto.time if realTimeBarTickProto.HasField('time') else 0
+ open_ = realTimeBarTickProto.open if realTimeBarTickProto.HasField('open') else 0.0
+ high = realTimeBarTickProto.high if realTimeBarTickProto.HasField('high') else 0.0
+ low = realTimeBarTickProto.low if realTimeBarTickProto.HasField('low') else 0.0
+ close = realTimeBarTickProto.close if realTimeBarTickProto.HasField('close') else 0.0
+ volume = Decimal(realTimeBarTickProto.volume) if realTimeBarTickProto.HasField('volume') else UNSET_DECIMAL
+ wap = Decimal(realTimeBarTickProto.WAP) if realTimeBarTickProto.HasField('WAP') else UNSET_DECIMAL
+ count = realTimeBarTickProto.count if realTimeBarTickProto.HasField('count') else 0
+
+ self.wrapper.realtimeBar(reqId, time, open_, high, low, close, volume, wap, count)
+
+ def processTickOptionComputationMsg(self, fields):
+ version = self.serverVersion
+ tickAttrib = None
+ optPrice = None
+ pvDividend = None
+ gamma = None
+ vega = None
+ theta = None
+ undPrice = None
+
+ if self.serverVersion < MIN_SERVER_VER_PRICE_BASED_VOLATILITY:
+ version = decode(int, fields)
+
+ reqId = decode(int, fields)
+ tickTypeInt = decode(int, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_PRICE_BASED_VOLATILITY:
+ tickAttrib = decode(int, fields)
+
+ impliedVol = decode(float, fields)
+ delta = decode(float, fields)
+
+ if impliedVol < 0: # -1 is the "not computed" indicator
+ impliedVol = None
+ if delta == -2: # -2 is the "not computed" indicator
+ delta = None
+
+ if (
+ version >= 6
+ or tickTypeInt == TickTypeEnum.MODEL_OPTION
+ or tickTypeInt == TickTypeEnum.DELAYED_MODEL_OPTION
+ ):
+ optPrice = decode(float, fields)
+ pvDividend = decode(float, fields)
+
+ if optPrice == -1: # -1 is the "not computed" indicator
+ optPrice = None
+ if pvDividend == -1: # -1 is the "not computed" indicator
+ pvDividend = None
+
+ if version >= 6:
+ gamma = decode(float, fields)
+ vega = decode(float, fields)
+ theta = decode(float, fields)
+ undPrice = decode(float, fields)
+
+ if gamma == -2: # -2 is the "not yet computed" indicator
+ gamma = None
+ if vega == -2: # -2 is the "not yet computed" indicator
+ vega = None
+ if theta == -2: # -2 is the "not yet computed" indicator
+ theta = None
+ if undPrice == -1: # -1 is the "not computed" indicator
+ undPrice = None
+
+ self.wrapper.tickOptionComputation(
+ reqId,
+ tickTypeInt,
+ tickAttrib,
+ impliedVol,
+ delta,
+ optPrice,
+ pvDividend,
+ gamma,
+ vega,
+ theta,
+ undPrice,
+ )
+
+ def processTickOptionComputationMsgProtoBuf(self, protobuf):
+ tickOptionComputationProto = TickOptionComputationProto()
+ tickOptionComputationProto.ParseFromString(protobuf)
+
+ self.wrapper.tickOptionComputationProtoBuf(tickOptionComputationProto)
+
+ reqId = tickOptionComputationProto.reqId if tickOptionComputationProto.HasField('reqId') else NO_VALID_ID
+ tickType = tickOptionComputationProto.tickType if tickOptionComputationProto.HasField('tickType') else UNSET_INTEGER
+ tickAttrib = tickOptionComputationProto.tickAttrib if tickOptionComputationProto.HasField('tickAttrib') else UNSET_INTEGER
+ impliedVol = tickOptionComputationProto.impliedVol if tickOptionComputationProto.HasField('impliedVol') else None
+ if impliedVol is not None and impliedVol < 0: # -1 is the "not computed" indicator
+ impliedVol = None
+ delta = tickOptionComputationProto.delta if tickOptionComputationProto.HasField('delta') else None
+ if delta is not None and delta == -2: # -2 is the "not computed" indicator
+ delta = None
+ optPrice = tickOptionComputationProto.optPrice if tickOptionComputationProto.HasField('optPrice') else None
+ if optPrice is not None and optPrice == -1: # -1 is the "not computed" indicator
+ optPrice = None
+ pvDividend = tickOptionComputationProto.pvDividend if tickOptionComputationProto.HasField('pvDividend') else None
+ if pvDividend is not None and pvDividend == -1: # -1 is the "not computed" indicator
+ pvDividend = None
+ gamma = tickOptionComputationProto.gamma if tickOptionComputationProto.HasField('gamma') else None
+ if gamma is not None and gamma == -2: # -2 is the "not yet computed" indicator
+ gamma = None
+ vega = tickOptionComputationProto.vega if tickOptionComputationProto.HasField('vega') else None
+ if vega is not None and vega == -2: # -2 is the "not yet computed" indicator
+ vega = None
+ theta = tickOptionComputationProto.theta if tickOptionComputationProto.HasField('theta') else None
+ if theta is not None and theta == -2: # -2 is the "not yet computed" indicator
+ theta = None
+ undPrice = tickOptionComputationProto.undPrice if tickOptionComputationProto.HasField('undPrice') else None
+ if undPrice is not None and undPrice == -1: # -1 is the "not computed" indicator
+ undPrice = None
+
+ self.wrapper.tickOptionComputation(reqId, tickType, tickAttrib, impliedVol, delta, optPrice, pvDividend, gamma, vega, theta, undPrice)
+
+ def processDeltaNeutralValidationMsg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+
+ deltaNeutralContract = DeltaNeutralContract()
+
+ deltaNeutralContract.conId = decode(int, fields)
+ deltaNeutralContract.delta = decode(float, fields)
+ deltaNeutralContract.price = decode(float, fields)
+
+ self.wrapper.deltaNeutralValidation(reqId, deltaNeutralContract)
+
+ def processMarketDataTypeMsg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+ marketDataType = decode(int, fields)
+
+ self.wrapper.marketDataType(reqId, marketDataType)
+
+ def processMarketDataTypeMsgProtoBuf(self, protobuf):
+ marketDataTypeProto = MarketDataTypeProto()
+ marketDataTypeProto.ParseFromString(protobuf)
+
+ self.wrapper.updateMarketDataTypeProtoBuf(marketDataTypeProto)
+
+ reqId = marketDataTypeProto.reqId if marketDataTypeProto.HasField('reqId') else NO_VALID_ID
+ marketDataType = marketDataTypeProto.marketDataType if marketDataTypeProto.HasField('marketDataType') else UNSET_INTEGER
+
+ self.wrapper.marketDataType(reqId, marketDataType)
+
+ def processCommissionAndFeesReportMsg(self, fields):
+ decode(int, fields)
+
+ commissionAndFeesReport = CommissionAndFeesReport()
+ commissionAndFeesReport.execId = decode(str, fields)
+ commissionAndFeesReport.commissionAndFees = decode(float, fields)
+ commissionAndFeesReport.currency = decode(str, fields)
+ commissionAndFeesReport.realizedPNL = decode(float, fields)
+ commissionAndFeesReport.yield_ = decode(float, fields)
+ commissionAndFeesReport.yieldRedemptionDate = decode(int, fields)
+
+ self.wrapper.commissionAndFeesReport(commissionAndFeesReport)
+
+ def processCommissionAndFeesReportMsgProtoBuf(self, protobuf):
+ commissionAndFeesReportProto = CommissionAndFeesReportProto()
+ commissionAndFeesReportProto.ParseFromString(protobuf)
+
+ self.wrapper.commissionAndFeesReportProtoBuf(commissionAndFeesReportProto)
+
+ commissionAndFeesReport = CommissionAndFeesReport()
+ commissionAndFeesReport.execId = commissionAndFeesReportProto.execId if commissionAndFeesReportProto.HasField('execId') else ""
+ commissionAndFeesReport.commissionAndFees = commissionAndFeesReportProto.commissionAndFees if commissionAndFeesReportProto.HasField('commissionAndFees') else 0.0
+ commissionAndFeesReport.currency = commissionAndFeesReportProto.currency if commissionAndFeesReportProto.HasField('currency') else ""
+ commissionAndFeesReport.realizedPNL = commissionAndFeesReportProto.realizedPNL if commissionAndFeesReportProto.HasField('realizedPNL') else 0.0
+ commissionAndFeesReport.yield_ = commissionAndFeesReportProto.bondYield if commissionAndFeesReportProto.HasField('bondYield') else 0.0
+ commissionAndFeesReport.yieldRedemptionDate = int(commissionAndFeesReportProto.yieldRedemptionDate) if commissionAndFeesReportProto.HasField('yieldRedemptionDate') else 0
+
+ self.wrapper.commissionAndFeesReport(commissionAndFeesReport)
+
+ def processPositionDataMsg(self, fields):
+ version = decode(int, fields)
+
+ account = decode(str, fields)
+
+ # decode contract fields
+ contract = Contract()
+ contract.conId = decode(int, fields)
+ contract.symbol = decode(str, fields)
+ contract.secType = decode(str, fields)
+ contract.lastTradeDateOrContractMonth = decode(str, fields)
+ contract.strike = decode(float, fields)
+ contract.right = decode(str, fields)
+ contract.multiplier = decode(str, fields)
+ contract.exchange = decode(str, fields)
+ contract.currency = decode(str, fields)
+ contract.localSymbol = decode(str, fields)
+ if version >= 2:
+ contract.tradingClass = decode(str, fields)
+
+ position = decode(Decimal, fields)
+
+ avgCost = 0.0
+ if version >= 3:
+ avgCost = decode(float, fields)
+
+ self.wrapper.position(account, contract, position, avgCost)
+
+ def processPositionMsgProtoBuf(self, protobuf):
+ positionProto = PositionProto()
+ positionProto.ParseFromString(protobuf)
+
+ self.wrapper.positionProtoBuf(positionProto)
+
+ # decode contract fields
+ if not positionProto.HasField('contract'):
+ return
+ contract = decodeContract(positionProto.contract)
+
+ position = Decimal(positionProto.position) if positionProto.HasField('position') else UNSET_DECIMAL
+ avgCost = positionProto.avgCost if positionProto.HasField('avgCost') else 0
+ account = positionProto.account if positionProto.HasField('account') else ""
+
+ self.wrapper.position(account, contract, position, avgCost)
+
+ def processPositionMultiMsg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+ account = decode(str, fields)
+
+ # decode contract fields
+ contract = Contract()
+ contract.conId = decode(int, fields)
+ contract.symbol = decode(str, fields)
+ contract.secType = decode(str, fields)
+ contract.lastTradeDateOrContractMonth = decode(str, fields)
+ contract.strike = decode(float, fields)
+ contract.right = decode(str, fields)
+ contract.multiplier = decode(str, fields)
+ contract.exchange = decode(str, fields)
+ contract.currency = decode(str, fields)
+ contract.localSymbol = decode(str, fields)
+ contract.tradingClass = decode(str, fields)
+ position = decode(Decimal, fields)
+ avgCost = decode(float, fields)
+ modelCode = decode(str, fields)
+
+ self.wrapper.positionMulti(
+ reqId, account, modelCode, contract, position, avgCost
+ )
+
+ def processPositionMultiMsgProtoBuf(self, protobuf):
+ positionMultiProto = PositionMultiProto()
+ positionMultiProto.ParseFromString(protobuf)
+
+ self.wrapper.positionMultiProtoBuf(positionMultiProto)
+
+ reqId = positionMultiProto.reqId if positionMultiProto.HasField('reqId') else NO_VALID_ID
+ account = positionMultiProto.account if positionMultiProto.HasField('account') else ""
+ modelCode = positionMultiProto.modelCode if positionMultiProto.HasField('modelCode') else ""
+
+ # decode contract fields
+ if not positionMultiProto.HasField('contract'):
+ return
+ contract = decodeContract(positionMultiProto.contract)
+
+ position = Decimal(positionMultiProto.position) if positionMultiProto.HasField('position') else UNSET_DECIMAL
+ avgCost = positionMultiProto.avgCost if positionMultiProto.HasField('avgCost') else 0
+
+ self.wrapper.positionMulti(reqId, account, modelCode, contract, position, avgCost)
+
+ def processSecurityDefinitionOptionParameterMsg(self, fields):
+ reqId = decode(int, fields)
+ exchange = decode(str, fields)
+ underlyingConId = decode(int, fields)
+ tradingClass = decode(str, fields)
+ multiplier = decode(str, fields)
+
+ expCount = decode(int, fields)
+ expirations = set()
+ for _ in range(expCount):
+ expiration = decode(str, fields)
+ expirations.add(expiration)
+
+ strikeCount = decode(int, fields)
+ strikes = set()
+ for _ in range(strikeCount):
+ strike = decode(float, fields)
+ strikes.add(strike)
+
+ self.wrapper.securityDefinitionOptionParameter(
+ reqId,
+ exchange,
+ underlyingConId,
+ tradingClass,
+ multiplier,
+ expirations,
+ strikes,
+ )
+
+ def processSecurityDefinitionOptionParameterMsgProtoBuf(self, protobuf):
+ secDefOptParameterProto = SecDefOptParameterProto()
+ secDefOptParameterProto.ParseFromString(protobuf)
+
+ self.wrapper.secDefOptParameterProtoBuf(secDefOptParameterProto)
+
+ reqId = secDefOptParameterProto.reqId if secDefOptParameterProto.HasField('reqId') else NO_VALID_ID
+ exchange = secDefOptParameterProto.exchange if secDefOptParameterProto.HasField('exchange') else ""
+ underlyingConId = secDefOptParameterProto.underlyingConId if secDefOptParameterProto.HasField('underlyingConId') else 0
+ tradingClass = secDefOptParameterProto.tradingClass if secDefOptParameterProto.HasField('tradingClass') else ""
+ multiplier = secDefOptParameterProto.multiplier if secDefOptParameterProto.HasField('multiplier') else ""
+
+ expirations = set()
+ if secDefOptParameterProto.expirations:
+ for expiration in secDefOptParameterProto.expirations:
+ expirations.add(expiration)
+
+ strikes = set()
+ if secDefOptParameterProto.strikes:
+ for strike in secDefOptParameterProto.strikes:
+ strikes.add(strike)
+
+ self.wrapper.securityDefinitionOptionParameter(reqId, exchange, underlyingConId, tradingClass, multiplier, expirations, strikes)
+
+ def processSecurityDefinitionOptionParameterEndMsg(self, fields):
+ reqId = decode(int, fields)
+ self.wrapper.securityDefinitionOptionParameterEnd(reqId)
+
+ def processSecurityDefinitionOptionParameterEndMsgProtoBuf(self, protobuf):
+ secDefOptParameterEndProto = SecDefOptParameterEndProto()
+ secDefOptParameterEndProto.ParseFromString(protobuf)
+
+ self.wrapper.secDefOptParameterEndProtoBuf(secDefOptParameterEndProto)
+
+ reqId = secDefOptParameterEndProto.reqId if secDefOptParameterEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.securityDefinitionOptionParameterEnd(reqId)
+
+ def processSoftDollarTiersMsg(self, fields):
+ reqId = decode(int, fields)
+ nTiers = decode(int, fields)
+
+ tiers = []
+ for _ in range(nTiers):
+ tier = SoftDollarTier()
+ tier.name = decode(str, fields)
+ tier.val = decode(str, fields)
+ tier.displayName = decode(str, fields)
+ tiers.append(tier)
+
+ self.wrapper.softDollarTiers(reqId, tiers)
+
+ def processSoftDollarTiersMsgProtoBuf(self, protobuf):
+ softDollarTiersProto = SoftDollarTiersProto()
+ softDollarTiersProto.ParseFromString(protobuf)
+
+ self.wrapper.softDollarTiersProtoBuf(softDollarTiersProto)
+
+ reqId = softDollarTiersProto.reqId if softDollarTiersProto.HasField('reqId') else NO_VALID_ID
+
+ tiers = []
+ if softDollarTiersProto.softDollarTiers:
+ for softDollarTierProto in softDollarTiersProto.softDollarTiers:
+ tier = decodeSoftDollarTier(softDollarTierProto)
+ if tier is not None: tiers.append(tier);
+
+ self.wrapper.softDollarTiers(reqId, tiers)
+
+ def processFamilyCodesMsg(self, fields):
+ nFamilyCodes = decode(int, fields)
+ familyCodes = []
+ for _ in range(nFamilyCodes):
+ famCode = FamilyCode()
+ famCode.accountID = decode(str, fields)
+ famCode.familyCodeStr = decode(str, fields)
+ familyCodes.append(famCode)
+
+ self.wrapper.familyCodes(familyCodes)
+
+ def processFamilyCodesMsgProtoBuf(self, protobuf):
+ familyCodesProto = FamilyCodesProto()
+ familyCodesProto.ParseFromString(protobuf)
+
+ self.wrapper.familyCodesProtoBuf(familyCodesProto)
+
+ familyCodes = []
+ if familyCodesProto.familyCodes:
+ for familCodeProto in familyCodesProto.familyCodes:
+ familyCode = decodeFamilyCode(familCodeProto)
+ familyCodes.append(familyCode)
+
+ self.wrapper.familyCodes(familyCodes)
+
+ def processSymbolSamplesMsg(self, fields):
+ reqId = decode(int, fields)
+ nContractDescriptions = decode(int, fields)
+ contractDescriptions = []
+ for _ in range(nContractDescriptions):
+ conDesc = ContractDescription()
+ conDesc.contract.conId = decode(int, fields)
+ conDesc.contract.symbol = decode(str, fields)
+ conDesc.contract.secType = decode(str, fields)
+ conDesc.contract.primaryExchange = decode(str, fields)
+ conDesc.contract.currency = decode(str, fields)
+
+ nDerivativeSecTypes = decode(int, fields)
+ conDesc.derivativeSecTypes = []
+ for _ in range(nDerivativeSecTypes):
+ derivSecType = decode(str, fields)
+ conDesc.derivativeSecTypes.append(derivSecType)
+ contractDescriptions.append(conDesc)
+
+ if self.serverVersion >= MIN_SERVER_VER_BOND_ISSUERID:
+ conDesc.contract.description = decode(str, fields)
+ conDesc.contract.issuerId = decode(str, fields)
+
+ self.wrapper.symbolSamples(reqId, contractDescriptions)
+
+
+ def processSymbolSamplesMsgProtoBuf(self, protobuf):
+ symbolSamplesProto = SymbolSamplesProto()
+ symbolSamplesProto.ParseFromString(protobuf)
+
+ self.wrapper.symbolSamplesProtoBuf(symbolSamplesProto)
+
+ reqId = symbolSamplesProto.reqId if symbolSamplesProto.HasField('reqId') else NO_VALID_ID
+
+ contractDescriptions = []
+ if symbolSamplesProto.contractDescriptions:
+ for contractDescriptionProto in symbolSamplesProto.contractDescriptions:
+ contract = Contract()
+ if contractDescriptionProto.HasField('contract'):
+ contract = decodeContract(contractDescriptionProto.contract)
+
+ derivativeSecTypes = []
+ if contractDescriptionProto.derivativeSecTypes:
+ for secType in contractDescriptionProto.derivativeSecTypes:
+ derivativeSecTypes.append(secType)
+
+ contracrDescription = ContractDescription()
+ contracrDescription.contract = contract
+ contracrDescription.derivativeSecTypes = derivativeSecTypes
+
+ contractDescriptions.append(contracrDescription)
+
+ self.wrapper.symbolSamples(reqId, contractDescriptions)
+
+ def processSmartComponents(self, fields):
+ reqId = decode(int, fields)
+ n = decode(int, fields)
+
+ smartComponentMap = []
+ for _ in range(n):
+ smartComponent = SmartComponent()
+ smartComponent.bitNumber = decode(int, fields)
+ smartComponent.exchange = decode(str, fields)
+ smartComponent.exchangeLetter = decode(str, fields)
+ smartComponentMap.append(smartComponent)
+
+ self.wrapper.smartComponents(reqId, smartComponentMap)
+
+ def processSmartComponentsMsgProtoBuf(self, protobuf):
+ smartComponentsProto = SmartComponentsProto()
+ smartComponentsProto.ParseFromString(protobuf)
+
+ self.wrapper.smartComponentsProtoBuf(smartComponentsProto)
+
+ reqId = smartComponentsProto.reqId if smartComponentsProto.HasField('reqId') else NO_VALID_ID
+
+ smartComponentsMap = []
+
+ smartComponentsMap = decodeSmartComponents(smartComponentsProto)
+
+ self.wrapper.smartComponents(reqId, smartComponentsMap)
+
+ def processTickReqParams(self, fields):
+ tickerId = decode(int, fields)
+ minTick = decode(float, fields)
+ bboExchange = decode(str, fields)
+ snapshotPermissions = decode(int, fields)
+ self.wrapper.tickReqParams(tickerId, minTick, bboExchange, snapshotPermissions)
+
+ def processTickReqParamsMsgProtoBuf(self, protobuf):
+ tickReqParamsProto = TickReqParamsProto()
+ tickReqParamsProto.ParseFromString(protobuf)
+
+ self.wrapper.tickReqParamsProtoBuf(tickReqParamsProto)
+
+ reqId = tickReqParamsProto.reqId if tickReqParamsProto.HasField('reqId') else NO_VALID_ID
+ minTick = float(tickReqParamsProto.minTick) if tickReqParamsProto.HasField('minTick') else UNSET_DOUBLE
+ bboExchange = tickReqParamsProto.bboExchange if tickReqParamsProto.HasField('bboExchange') else ""
+ snapshotPermissions = tickReqParamsProto.snapshotPermissions if tickReqParamsProto.HasField('snapshotPermissions') else UNSET_INTEGER
+
+ self.wrapper.tickReqParams(reqId, minTick, bboExchange, snapshotPermissions)
+
+ def processMktDepthExchanges(self, fields):
+ depthMktDataDescriptions = []
+ nDepthMktDataDescriptions = decode(int, fields)
+
+ if nDepthMktDataDescriptions > 0:
+ for _ in range(nDepthMktDataDescriptions):
+ desc = DepthMktDataDescription()
+ desc.exchange = decode(str, fields)
+ desc.secType = decode(str, fields)
+ if self.serverVersion >= MIN_SERVER_VER_SERVICE_DATA_TYPE:
+ desc.listingExch = decode(str, fields)
+ desc.serviceDataType = decode(str, fields)
+ desc.aggGroup = decode(int, fields)
+ else:
+ decode(int, fields) # boolean notSuppIsL2
+ depthMktDataDescriptions.append(desc)
+
+ self.wrapper.mktDepthExchanges(depthMktDataDescriptions)
+
+ def processMktDepthExchangesMsgProtoBuf(self, protobuf):
+ marketDepthExchangesProto = MarketDepthExchangesProto()
+ marketDepthExchangesProto.ParseFromString(protobuf)
+
+ self.wrapper.marketDepthExchangesProtoBuf(marketDepthExchangesProto)
+
+ depthMktDataDescriptions = []
+ if marketDepthExchangesProto.depthMarketDataDescriptions:
+ for depthMarketDataDescriptionProto in marketDepthExchangesProto.depthMarketDataDescriptions:
+ depthMktDataDescriptions.append(decodeDepthMarketDataDescription(depthMarketDataDescriptionProto))
+
+ self.wrapper.mktDepthExchanges(depthMktDataDescriptions)
+
+ def processHeadTimestamp(self, fields):
+ reqId = decode(int, fields)
+ headTimestamp = decode(str, fields)
+ self.wrapper.headTimestamp(reqId, headTimestamp)
+
+ def processHeadTimestampMsgProtoBuf(self, protobuf):
+ headTimestampProto = HeadTimestampProto()
+ headTimestampProto.ParseFromString(protobuf)
+
+ self.wrapper.headTimestampProtoBuf(headTimestampProto)
+
+ reqId = headTimestampProto.reqId if headTimestampProto.HasField('reqId') else NO_VALID_ID
+ headTimestamp = headTimestampProto.headTimestamp if headTimestampProto.HasField('headTimestamp') else ""
+
+ self.wrapper.headTimestamp(reqId, headTimestamp)
+
+ def processTickNews(self, fields):
+ tickerId = decode(int, fields)
+ timeStamp = decode(int, fields)
+ providerCode = decode(str, fields)
+ articleId = decode(str, fields)
+ headline = decode(str, fields)
+ extraData = decode(str, fields)
+ self.wrapper.tickNews(
+ tickerId, timeStamp, providerCode, articleId, headline, extraData
+ )
+
+ def processTickNewsMsgProtoBuf(self, protobuf):
+ tickNewsProto = TickNewsProto()
+ tickNewsProto.ParseFromString(protobuf)
+
+ self.wrapper.tickNewsProtoBuf(tickNewsProto)
+
+ reqId = tickNewsProto.reqId if tickNewsProto.HasField('reqId') else NO_VALID_ID
+ timestamp = tickNewsProto.timestamp if tickNewsProto.HasField('timestamp') else 0
+ providerCode = tickNewsProto.providerCode if tickNewsProto.HasField('providerCode') else ""
+ articleId = tickNewsProto.articleId if tickNewsProto.HasField('articleId') else ""
+ headline = tickNewsProto.headline if tickNewsProto.HasField('headline') else ""
+ extraData = tickNewsProto.extraData if tickNewsProto.HasField('extraData') else ""
+
+ self.wrapper.tickNews(reqId, timestamp, providerCode, articleId, headline, extraData)
+
+ def processNewsProviders(self, fields):
+ newsProviders = []
+ nNewsProviders = decode(int, fields)
+ if nNewsProviders > 0:
+ for _ in range(nNewsProviders):
+ provider = NewsProvider()
+ provider.code = decode(str, fields)
+ provider.name = decode(str, fields)
+ newsProviders.append(provider)
+
+ self.wrapper.newsProviders(newsProviders)
+
+ def processNewsProvidersMsgProtoBuf(self, protobuf):
+ newsProvidersProto = NewsProvidersProto()
+ newsProvidersProto.ParseFromString(protobuf)
+
+ self.wrapper.newsProvidersProtoBuf(newsProvidersProto)
+
+ newsProviders = []
+ if newsProvidersProto.newsProviders:
+ for newsProviderProto in newsProvidersProto.newsProviders:
+ newsProvider = NewsProvider()
+ newsProvider.code = newsProviderProto.providerCode if newsProviderProto.HasField('providerCode') else ""
+ newsProvider.name = newsProviderProto.providerName if newsProviderProto.HasField('providerName') else ""
+ newsProviders.append(newsProvider)
+
+ self.wrapper.newsProviders(newsProviders)
+
+ def processNewsArticle(self, fields):
+ reqId = decode(int, fields)
+ articleType = decode(int, fields)
+ articleText = decode(str, fields)
+ self.wrapper.newsArticle(reqId, articleType, articleText)
+
+ def processNewsArticleMsgProtoBuf(self, protobuf):
+ newsArticleProto = NewsArticleProto()
+ newsArticleProto.ParseFromString(protobuf)
+
+ self.wrapper.newsArticleProtoBuf(newsArticleProto)
+
+ reqId = newsArticleProto.reqId if newsArticleProto.HasField('reqId') else NO_VALID_ID
+ articleType = newsArticleProto.articleType if newsArticleProto.HasField('articleType') else 0
+ articleText = newsArticleProto.articleText if newsArticleProto.HasField('articleText') else ""
+
+ self.wrapper.newsArticle(reqId, articleType, articleText)
+
+ def processHistoricalNews(self, fields):
+ requestId = decode(int, fields)
+ time = decode(str, fields)
+ providerCode = decode(str, fields)
+ articleId = decode(str, fields)
+ headline = decode(str, fields)
+ self.wrapper.historicalNews(requestId, time, providerCode, articleId, headline)
+
+ def processHistoricalNewsMsgProtoBuf(self, protobuf):
+ historicalNewsProto = HistoricalNewsProto()
+ historicalNewsProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalNewsProtoBuf(historicalNewsProto)
+
+ reqId = historicalNewsProto.reqId if historicalNewsProto.HasField('reqId') else NO_VALID_ID
+ time = historicalNewsProto.time if historicalNewsProto.HasField('time') else ""
+ providerCode = historicalNewsProto.providerCode if historicalNewsProto.HasField('providerCode') else ""
+ articleId = historicalNewsProto.articleId if historicalNewsProto.HasField('articleId') else ""
+ headline = historicalNewsProto.headline if historicalNewsProto.HasField('headline') else ""
+
+ self.wrapper.historicalNews(reqId, time, providerCode, articleId, headline)
+
+ def processHistoricalNewsEnd(self, fields):
+ reqId = decode(int, fields)
+ hasMore = decode(bool, fields)
+ self.wrapper.historicalNewsEnd(reqId, hasMore)
+
+ def processHistoricalNewsEndMsgProtoBuf(self, protobuf):
+ historicalNewsEndProto = HistoricalNewsEndProto()
+ historicalNewsEndProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalNewsEndProtoBuf(historicalNewsEndProto)
+
+ reqId = historicalNewsEndProto.reqId if historicalNewsEndProto.HasField('reqId') else NO_VALID_ID
+ hasMore = historicalNewsEndProto.hasMore if historicalNewsEndProto.HasField('hasMore') else False
+
+ self.wrapper.historicalNewsEnd(reqId, hasMore)
+
+ def processHistogramData(self, fields):
+ reqId = decode(int, fields)
+ numPoints = decode(int, fields)
+
+ histogram = []
+ for _ in range(numPoints):
+ dataPoint = HistogramData()
+ dataPoint.price = decode(float, fields)
+ dataPoint.size = decode(Decimal, fields)
+ histogram.append(dataPoint)
+
+ self.wrapper.histogramData(reqId, histogram)
+
+ def processHistogramDataMsgProtoBuf(self, protobuf):
+ histogramDataProto = HistogramDataProto()
+ histogramDataProto.ParseFromString(protobuf)
+
+ self.wrapper.histogramDataProtoBuf(histogramDataProto)
+
+ reqId = histogramDataProto.reqId if histogramDataProto.HasField('reqId') else NO_VALID_ID
+
+ histogram = []
+ if histogramDataProto.histogramDataEntries:
+ for histogramDataEntryProto in histogramDataProto.histogramDataEntries:
+ histogramEntry = decodeHistogramDataEntry(histogramDataEntryProto)
+ histogram.append(histogramEntry)
+
+ self.wrapper.histogramData(reqId, histogram)
+
+ def processRerouteMktDataReq(self, fields):
+ reqId = decode(int, fields)
+ conId = decode(int, fields)
+ exchange = decode(str, fields)
+
+ self.wrapper.rerouteMktDataReq(reqId, conId, exchange)
+
+ def processRerouteMktDataReqMsgProtoBuf(self, protobuf):
+ rerouteMarketDataRequestProto = RerouteMarketDataRequestProto()
+ rerouteMarketDataRequestProto.ParseFromString(protobuf)
+
+ self.wrapper.rerouteMarketDataRequestProtoBuf(rerouteMarketDataRequestProto)
+
+ reqId = rerouteMarketDataRequestProto.reqId if rerouteMarketDataRequestProto.HasField('reqId') else NO_VALID_ID
+ conId = rerouteMarketDataRequestProto.conId if rerouteMarketDataRequestProto.HasField('conId') else 0
+ exchange = rerouteMarketDataRequestProto.exchange if rerouteMarketDataRequestProto.HasField('exchange') else ""
+
+ self.wrapper.rerouteMktDataReq(reqId, conId, exchange)
+
+ def processRerouteMktDepthReq(self, fields):
+ reqId = decode(int, fields)
+ conId = decode(int, fields)
+ exchange = decode(str, fields)
+
+ self.wrapper.rerouteMktDepthReq(reqId, conId, exchange)
+
+ def processRerouteMktDepthReqMsgProtoBuf(self, protobuf):
+ rerouteMarketDepthRequestProto = RerouteMarketDepthRequestProto()
+ rerouteMarketDepthRequestProto.ParseFromString(protobuf)
+
+ self.wrapper.rerouteMarketDepthRequestProtoBuf(rerouteMarketDepthRequestProto)
+
+ reqId = rerouteMarketDepthRequestProto.reqId if rerouteMarketDepthRequestProto.HasField('reqId') else NO_VALID_ID
+ conId = rerouteMarketDepthRequestProto.conId if rerouteMarketDepthRequestProto.HasField('conId') else 0
+ exchange = rerouteMarketDepthRequestProto.exchange if rerouteMarketDepthRequestProto.HasField('exchange') else ""
+
+ self.wrapper.rerouteMktDepthReq(reqId, conId, exchange)
+
+ def processMarketRuleMsg(self, fields):
+ marketRuleId = decode(int, fields)
+
+ nPriceIncrements = decode(int, fields)
+ priceIncrements = []
+
+ if nPriceIncrements > 0:
+ for _ in range(nPriceIncrements):
+ prcInc = PriceIncrement()
+ prcInc.lowEdge = decode(float, fields)
+ prcInc.increment = decode(float, fields)
+ priceIncrements.append(prcInc)
+
+ self.wrapper.marketRule(marketRuleId, priceIncrements)
+
+ def processMarketRuleMsgProtoBuf(self, protobuf):
+ marketRuleProto = MarketRuleProto()
+ marketRuleProto.ParseFromString(protobuf)
+
+ self.wrapper.marketRuleProtoBuf(marketRuleProto)
+
+ marketRuleId = marketRuleProto.marketRuleId if marketRuleProto.HasField('marketRuleId') else 0
+
+ priceIncrements = []
+ if marketRuleProto.priceIncrements:
+ for priceIncrementProto in marketRuleProto.priceIncrements:
+ priceIncrement = decodePriceIncrement(priceIncrementProto)
+ priceIncrements.append(priceIncrement)
+
+ self.wrapper.marketRule(marketRuleId, priceIncrements)
+
+ def processPnLMsg(self, fields):
+ reqId = decode(int, fields)
+ dailyPnL = decode(float, fields)
+ unrealizedPnL = None
+ realizedPnL = None
+
+ if self.serverVersion >= MIN_SERVER_VER_UNREALIZED_PNL:
+ unrealizedPnL = decode(float, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_REALIZED_PNL:
+ realizedPnL = decode(float, fields)
+
+ self.wrapper.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL)
+
+ def processPnLMsgProtoBuf(self, protobuf):
+ pnlProto = PnLProto()
+ pnlProto.ParseFromString(protobuf)
+
+ self.wrapper.pnlProtoBuf(pnlProto)
+
+ reqId = pnlProto.reqId if pnlProto.HasField('reqId') else NO_VALID_ID
+ dailyPnL = pnlProto.dailyPnL if pnlProto.HasField('dailyPnL') else UNSET_DOUBLE
+ unrealizedPnL = pnlProto.unrealizedPnL if pnlProto.HasField('unrealizedPnL') else UNSET_DOUBLE
+ realizedPnL = pnlProto.realizedPnL if pnlProto.HasField('realizedPnL') else UNSET_DOUBLE
+
+ self.wrapper.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL)
+
+ def processPnLSingleMsg(self, fields):
+ reqId = decode(int, fields)
+ pos = decode(Decimal, fields)
+ dailyPnL = decode(float, fields)
+ unrealizedPnL = None
+ realizedPnL = None
+
+ if self.serverVersion >= MIN_SERVER_VER_UNREALIZED_PNL:
+ unrealizedPnL = decode(float, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_REALIZED_PNL:
+ realizedPnL = decode(float, fields)
+
+ value = decode(float, fields)
+
+ self.wrapper.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value)
+
+ def processPnLSingleMsgProtoBuf(self, protobuf):
+ pnlSingleProto = PnLSingleProto()
+ pnlSingleProto.ParseFromString(protobuf)
+
+ self.wrapper.pnlSingleProtoBuf(pnlSingleProto)
+
+ reqId = pnlSingleProto.reqId if pnlSingleProto.HasField('reqId') else NO_VALID_ID
+ pos = Decimal(pnlSingleProto.position) if pnlSingleProto.HasField('position') else UNSET_DECIMAL
+ dailyPnL = pnlSingleProto.dailyPnL if pnlSingleProto.HasField('dailyPnL') else UNSET_DOUBLE
+ unrealizedPnL = pnlSingleProto.unrealizedPnL if pnlSingleProto.HasField('unrealizedPnL') else UNSET_DOUBLE
+ realizedPnL = pnlSingleProto.realizedPnL if pnlSingleProto.HasField('realizedPnL') else UNSET_DOUBLE
+ value = pnlSingleProto.value if pnlSingleProto.HasField('value') else UNSET_DOUBLE
+
+ self.wrapper.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value)
+
+ def processHistoricalTicks(self, fields):
+ reqId = decode(int, fields)
+ tickCount = decode(int, fields)
+
+ ticks = []
+
+ for _ in range(tickCount):
+ historicalTick = HistoricalTick()
+ historicalTick.time = decode(int, fields)
+ next(fields) # for consistency
+ historicalTick.price = decode(float, fields)
+ historicalTick.size = decode(Decimal, fields)
+ ticks.append(historicalTick)
+
+ done = decode(bool, fields)
+
+ self.wrapper.historicalTicks(reqId, ticks, done)
+
+ def processHistoricalTicksMsgProtoBuf(self, protobuf):
+ historicalTicksProto = HistoricalTicksProto()
+ historicalTicksProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalTicksProtoBuf(historicalTicksProto)
+
+ reqId = historicalTicksProto.reqId if historicalTicksProto.HasField('reqId') else NO_VALID_ID
+ isDone = historicalTicksProto.isDone if historicalTicksProto.HasField('isDone') else False
+
+ historicalTicks = []
+ if historicalTicksProto.historicalTicks:
+ for historicalTickProto in historicalTicksProto.historicalTicks:
+ historicalTick = decodeHistoricalTick(historicalTickProto)
+ historicalTicks.append(historicalTick)
+
+ self.wrapper.historicalTicks(reqId, historicalTicks, isDone)
+
+ def processHistoricalTicksBidAsk(self, fields):
+ reqId = decode(int, fields)
+ tickCount = decode(int, fields)
+
+ ticks = []
+
+ for _ in range(tickCount):
+ historicalTickBidAsk = HistoricalTickBidAsk()
+ historicalTickBidAsk.time = decode(int, fields)
+ mask = decode(int, fields)
+ tickAttribBidAsk = TickAttribBidAsk()
+ tickAttribBidAsk.askPastHigh = mask & 1 != 0
+ tickAttribBidAsk.bidPastLow = mask & 2 != 0
+ historicalTickBidAsk.tickAttribBidAsk = tickAttribBidAsk
+ historicalTickBidAsk.priceBid = decode(float, fields)
+ historicalTickBidAsk.priceAsk = decode(float, fields)
+ historicalTickBidAsk.sizeBid = decode(Decimal, fields)
+ historicalTickBidAsk.sizeAsk = decode(Decimal, fields)
+ ticks.append(historicalTickBidAsk)
+
+ done = decode(bool, fields)
+
+ self.wrapper.historicalTicksBidAsk(reqId, ticks, done)
+
+ def processHistoricalTicksBidAskMsgProtoBuf(self, protobuf):
+ historicalTicksBidAskProto = HistoricalTicksBidAskProto()
+ historicalTicksBidAskProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalTicksBidAskProtoBuf(historicalTicksBidAskProto)
+
+ reqId = historicalTicksBidAskProto.reqId if historicalTicksBidAskProto.HasField('reqId') else NO_VALID_ID
+ isDone = historicalTicksBidAskProto.isDone if historicalTicksBidAskProto.HasField('isDone') else False
+
+ historicalTicksBidAsk = []
+ if historicalTicksBidAskProto.historicalTicksBidAsk:
+ for historicalTickBidAskProto in historicalTicksBidAskProto.historicalTicksBidAsk:
+ historicalTickBidAsk = decodeHistoricalTickBidAsk(historicalTickBidAskProto)
+ historicalTicksBidAsk.append(historicalTickBidAsk)
+
+ self.wrapper.historicalTicksBidAsk(reqId, historicalTicksBidAsk, isDone)
+
+ def processHistoricalTicksLast(self, fields):
+ reqId = decode(int, fields)
+ tickCount = decode(int, fields)
+
+ ticks = []
+
+ for _ in range(tickCount):
+ historicalTickLast = HistoricalTickLast()
+ historicalTickLast.time = decode(int, fields)
+ mask = decode(int, fields)
+ tickAttribLast = TickAttribLast()
+ tickAttribLast.pastLimit = mask & 1 != 0
+ tickAttribLast.unreported = mask & 2 != 0
+ historicalTickLast.tickAttribLast = tickAttribLast
+ historicalTickLast.price = decode(float, fields)
+ historicalTickLast.size = decode(Decimal, fields)
+ historicalTickLast.exchange = decode(str, fields)
+ historicalTickLast.specialConditions = decode(str, fields)
+ ticks.append(historicalTickLast)
+
+ done = decode(bool, fields)
+
+ self.wrapper.historicalTicksLast(reqId, ticks, done)
+
+ def processHistoricalTicksLastMsgProtoBuf(self, protobuf):
+ historicalTicksLastProto = HistoricalTicksLastProto()
+ historicalTicksLastProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalTicksLastProtoBuf(historicalTicksLastProto)
+
+ reqId = historicalTicksLastProto.reqId if historicalTicksLastProto.HasField('reqId') else NO_VALID_ID
+ isDone = historicalTicksLastProto.isDone if historicalTicksLastProto.HasField('isDone') else False
+
+ historicalTicksLast = []
+ if historicalTicksLastProto.historicalTicksLast:
+ for historicalTickLastProto in historicalTicksLastProto.historicalTicksLast:
+ historicalTickLast = decodeHistoricalTickLast(historicalTickLastProto)
+ historicalTicksLast.append(historicalTickLast)
+
+ self.wrapper.historicalTicksLast(reqId, historicalTicksLast, isDone)
+
+ def processTickByTickMsg(self, fields):
+ reqId = decode(int, fields)
+ tickType = decode(int, fields)
+ time = decode(int, fields)
+
+ if tickType == 0:
+ # None
+ pass
+ elif tickType == 1 or tickType == 2:
+ # Last or AllLast
+ price = decode(float, fields)
+ size = decode(Decimal, fields)
+ mask = decode(int, fields)
+
+ tickAttribLast = TickAttribLast()
+ tickAttribLast.pastLimit = mask & 1 != 0
+ tickAttribLast.unreported = mask & 2 != 0
+ exchange = decode(str, fields)
+ specialConditions = decode(str, fields)
+
+ self.wrapper.tickByTickAllLast(
+ reqId,
+ tickType,
+ time,
+ price,
+ size,
+ tickAttribLast,
+ exchange,
+ specialConditions,
+ )
+ elif tickType == 3:
+ # BidAsk
+ bidPrice = decode(float, fields)
+ askPrice = decode(float, fields)
+ bidSize = decode(Decimal, fields)
+ askSize = decode(Decimal, fields)
+ mask = decode(int, fields)
+ tickAttribBidAsk = TickAttribBidAsk()
+ tickAttribBidAsk.bidPastLow = mask & 1 != 0
+ tickAttribBidAsk.askPastHigh = mask & 2 != 0
+
+ self.wrapper.tickByTickBidAsk(
+ reqId, time, bidPrice, askPrice, bidSize, askSize, tickAttribBidAsk
+ )
+ elif tickType == 4:
+ # MidPoint
+ midPoint = decode(float, fields)
+
+ self.wrapper.tickByTickMidPoint(reqId, time, midPoint)
+
+ def processTickByTickMsgProtoBuf(self, protobuf):
+ tickByTickDataProto = TickByTickDataProto()
+ tickByTickDataProto.ParseFromString(protobuf)
+
+ self.wrapper.tickByTickDataProtoBuf(tickByTickDataProto)
+
+ reqId = tickByTickDataProto.reqId if tickByTickDataProto.HasField('reqId') else NO_VALID_ID
+ tickType = tickByTickDataProto.tickType if tickByTickDataProto.HasField('tickType') else 0
+
+ if tickType == 0:
+ # None
+ pass
+ elif tickType == 1 or tickType == 2:
+ # Last or AllLast
+ if tickByTickDataProto.HasField('historicalTickLast'):
+ historicalTickLast = decodeHistoricalTickLast(tickByTickDataProto.historicalTickLast)
+ self.wrapper.tickByTickAllLast(
+ reqId,
+ tickType,
+ historicalTickLast.time,
+ historicalTickLast.price,
+ historicalTickLast.size,
+ historicalTickLast.tickAttribLast,
+ historicalTickLast.exchange,
+ historicalTickLast.specialConditions
+ )
+ elif tickType == 3:
+ # BidAsk
+ if tickByTickDataProto.HasField('historicalTickBidAsk'):
+ historicalTickBidAsk = decodeHistoricalTickBidAsk(tickByTickDataProto.historicalTickBidAsk)
+ self.wrapper.tickByTickBidAsk(
+ reqId,
+ historicalTickBidAsk.time,
+ historicalTickBidAsk.priceBid,
+ historicalTickBidAsk.priceAsk,
+ historicalTickBidAsk.sizeBid,
+ historicalTickBidAsk.sizeAsk,
+ historicalTickBidAsk.tickAttribBidAsk
+ )
+ elif tickType == 4:
+ # MidPoint
+ if tickByTickDataProto.HasField('historicalTickMidPoint'):
+ historicalTick = decodeHistoricalTick(tickByTickDataProto.historicalTickMidPoint)
+ self.wrapper.tickByTickMidPoint(reqId, historicalTick.time, historicalTick.price)
+
+ def processOrderBoundMsg(self, fields):
+ permId = decode(int, fields)
+ clientId = decode(int, fields)
+ orderId = decode(int, fields)
+
+ self.wrapper.orderBound(permId, clientId, orderId)
+
+ def processOrderBoundMsgProtoBuf(self, protobuf):
+ orderBoundProto = OrderBoundProto()
+ orderBoundProto.ParseFromString(protobuf)
+
+ self.wrapper.orderBoundProtoBuf(orderBoundProto)
+
+ permId = orderBoundProto.permId if orderBoundProto.HasField('permId') else UNSET_LONG
+ clientId = orderBoundProto.clientId if orderBoundProto.HasField('clientId') else UNSET_INTEGER
+ orderId = orderBoundProto.orderId if orderBoundProto.HasField('orderId') else UNSET_INTEGER
+
+ self.wrapper.orderBound(permId, clientId, orderId)
+
+ def processMarketDepthMsg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+
+ position = decode(int, fields)
+ operation = decode(int, fields)
+ side = decode(int, fields)
+ price = decode(float, fields)
+ size = decode(Decimal, fields)
+
+ self.wrapper.updateMktDepth(reqId, position, operation, side, price, size)
+
+ def processMarketDepthMsgProtoBuf(self, protobuf):
+ marketDepthProto = MarketDepthProto()
+ marketDepthProto.ParseFromString(protobuf)
+
+ self.wrapper.updateMarketDepthProtoBuf(marketDepthProto)
+
+ reqId = marketDepthProto.reqId if marketDepthProto.HasField('reqId') else NO_VALID_ID
+
+ # decode market depth fields
+ if not marketDepthProto.HasField('marketDepthData'):
+ return
+ marketDepthDataProto = marketDepthProto.marketDepthData
+
+ position = marketDepthDataProto.position if marketDepthDataProto.HasField('position') else UNSET_INTEGER
+ operation = marketDepthDataProto.operation if marketDepthDataProto.HasField('operation') else UNSET_INTEGER
+ side = marketDepthDataProto.side if marketDepthDataProto.HasField('side') else UNSET_INTEGER
+ price = marketDepthDataProto.price if marketDepthDataProto.HasField('price') else UNSET_DOUBLE
+ size = Decimal(marketDepthDataProto.size) if marketDepthDataProto.HasField('size') else UNSET_DECIMAL
+
+ self.wrapper.updateMktDepth(reqId, position, operation, side, price, size)
+
+ def processMarketDepthL2Msg(self, fields):
+ decode(int, fields)
+ reqId = decode(int, fields)
+
+ position = decode(int, fields)
+ marketMaker = decode(str, fields)
+ operation = decode(int, fields)
+ side = decode(int, fields)
+ price = decode(float, fields)
+ size = decode(Decimal, fields)
+ isSmartDepth = False
+
+ if self.serverVersion >= MIN_SERVER_VER_SMART_DEPTH:
+ isSmartDepth = decode(bool, fields)
+
+ self.wrapper.updateMktDepthL2(
+ reqId, position, marketMaker, operation, side, price, size, isSmartDepth
+ )
+
+ def processMarketDepthL2MsgProtoBuf(self, protobuf):
+ marketDepthL2Proto = MarketDepthL2Proto()
+ marketDepthL2Proto.ParseFromString(protobuf)
+
+ self.wrapper.updateMarketDepthL2ProtoBuf(marketDepthL2Proto)
+
+ reqId = marketDepthL2Proto.reqId if marketDepthL2Proto.HasField('reqId') else NO_VALID_ID
+
+ # decode market depth fields
+ if not marketDepthL2Proto.HasField('marketDepthData'):
+ return
+ marketDepthDataProto = marketDepthL2Proto.marketDepthData
+
+ position = marketDepthDataProto.position if marketDepthDataProto.HasField('position') else 0
+ marketMaker = marketDepthDataProto.marketMaker if marketDepthDataProto.HasField('marketMaker') else ""
+ operation = marketDepthDataProto.operation if marketDepthDataProto.HasField('operation') else UNSET_INTEGER
+ side = marketDepthDataProto.side if marketDepthDataProto.HasField('side') else UNSET_INTEGER
+ price = marketDepthDataProto.price if marketDepthDataProto.HasField('price') else UNSET_DOUBLE
+ size = Decimal(marketDepthDataProto.size) if marketDepthDataProto.HasField('size') else UNSET_DECIMAL
+ isSmartDepth = marketDepthDataProto.isSmartDepth if marketDepthDataProto.HasField('isSmartDepth') else False
+
+ self.wrapper.updateMktDepthL2(reqId, position, marketMaker, operation, side, price, size, isSmartDepth)
+
+ def processCompletedOrderMsg(self, fields):
+ order = Order()
+ contract = Contract()
+ orderState = OrderState()
+
+ OrderDecoder.__init__(
+ self, contract, order, orderState, UNSET_INTEGER, self.serverVersion
+ )
+
+ # read contract fields
+ OrderDecoder.decodeContractFields(self, fields)
+
+ # read order fields
+ OrderDecoder.decodeAction(self, fields)
+ OrderDecoder.decodeTotalQuantity(self, fields)
+ OrderDecoder.decodeOrderType(self, fields)
+ OrderDecoder.decodeLmtPrice(self, fields)
+ OrderDecoder.decodeAuxPrice(self, fields)
+ OrderDecoder.decodeTIF(self, fields)
+ OrderDecoder.decodeOcaGroup(self, fields)
+ OrderDecoder.decodeAccount(self, fields)
+ OrderDecoder.decodeOpenClose(self, fields)
+ OrderDecoder.decodeOrigin(self, fields)
+ OrderDecoder.decodeOrderRef(self, fields)
+ OrderDecoder.decodePermId(self, fields)
+ OrderDecoder.decodeOutsideRth(self, fields)
+ OrderDecoder.decodeHidden(self, fields)
+ OrderDecoder.decodeDiscretionaryAmt(self, fields)
+ OrderDecoder.decodeGoodAfterTime(self, fields)
+ OrderDecoder.decodeFAParams(self, fields)
+ OrderDecoder.decodeModelCode(self, fields)
+ OrderDecoder.decodeGoodTillDate(self, fields)
+ OrderDecoder.decodeRule80A(self, fields)
+ OrderDecoder.decodePercentOffset(self, fields)
+ OrderDecoder.decodeSettlingFirm(self, fields)
+ OrderDecoder.decodeShortSaleParams(self, fields)
+ OrderDecoder.decodeBoxOrderParams(self, fields)
+ OrderDecoder.decodePegToStkOrVolOrderParams(self, fields)
+ OrderDecoder.decodeDisplaySize(self, fields)
+ OrderDecoder.decodeSweepToFill(self, fields)
+ OrderDecoder.decodeAllOrNone(self, fields)
+ OrderDecoder.decodeMinQty(self, fields)
+ OrderDecoder.decodeOcaType(self, fields)
+ OrderDecoder.decodeTriggerMethod(self, fields)
+ OrderDecoder.decodeVolOrderParams(self, fields, False)
+ OrderDecoder.decodeTrailParams(self, fields)
+ OrderDecoder.decodeComboLegs(self, fields)
+ OrderDecoder.decodeSmartComboRoutingParams(self, fields)
+ OrderDecoder.decodeScaleOrderParams(self, fields)
+ OrderDecoder.decodeHedgeParams(self, fields)
+ OrderDecoder.decodeClearingParams(self, fields)
+ OrderDecoder.decodeNotHeld(self, fields)
+ OrderDecoder.decodeDeltaNeutral(self, fields)
+ OrderDecoder.decodeAlgoParams(self, fields)
+ OrderDecoder.decodeSolicited(self, fields)
+ OrderDecoder.decodeOrderStatus(self, fields)
+ OrderDecoder.decodeVolRandomizeFlags(self, fields)
+ OrderDecoder.decodePegToBenchParams(self, fields)
+ OrderDecoder.decodeConditions(self, fields)
+ OrderDecoder.decodeStopPriceAndLmtPriceOffset(self, fields)
+ OrderDecoder.decodeCashQty(self, fields)
+ OrderDecoder.decodeDontUseAutoPriceForHedge(self, fields)
+ OrderDecoder.decodeIsOmsContainers(self, fields)
+ OrderDecoder.decodeAutoCancelDate(self, fields)
+ OrderDecoder.decodeFilledQuantity(self, fields)
+ OrderDecoder.decodeRefFuturesConId(self, fields)
+ OrderDecoder.decodeAutoCancelParent(self, fields)
+ OrderDecoder.decodeShareholder(self, fields)
+ OrderDecoder.decodeImbalanceOnly(self, fields)
+ OrderDecoder.decodeRouteMarketableToBbo(self, fields)
+ OrderDecoder.decodeParentPermId(self, fields)
+ OrderDecoder.decodeCompletedTime(self, fields)
+ OrderDecoder.decodeCompletedStatus(self, fields)
+ OrderDecoder.decodePegBestPegMidOrderAttributes(self, fields)
+ OrderDecoder.decodeCustomerAccount(self, fields)
+ OrderDecoder.decodeProfessionalCustomer(self, fields)
+ OrderDecoder.decodeSubmitter(self, fields)
+
+ self.wrapper.completedOrder(contract, order, orderState)
+
+ def processCompletedOrderMsgProtoBuf(self, protobuf):
+ completedOrderProto = CompletedOrderProto()
+ completedOrderProto.ParseFromString(protobuf)
+
+ self.wrapper.completedOrderProtoBuf(completedOrderProto)
+
+ # decode contract fields
+ if not completedOrderProto.HasField('contract'):
+ return
+ contract = decodeContract(completedOrderProto.contract)
+
+ # decode order fields
+ if not completedOrderProto.HasField('order'):
+ return
+ order = decodeOrder(UNSET_INTEGER, completedOrderProto.contract, completedOrderProto.order)
+
+ # decode order state fields
+ if not completedOrderProto.HasField('orderState'):
+ return
+ orderState = decodeOrderState(completedOrderProto.orderState)
+
+ self.wrapper.completedOrder(contract, order, orderState);
+
+ def processCompletedOrdersEndMsg(self, fields):
+ self.wrapper.completedOrdersEnd()
+
+ def processCompletedOrdersEndMsgProtoBuf(self, protobuf):
+ completedOrdersEndProto = CompletedOrdersEndProto()
+ completedOrdersEndProto.ParseFromString(protobuf)
+
+ self.wrapper.completedOrdersEndProtoBuf(completedOrdersEndProto)
+
+ self.wrapper.completedOrdersEnd()
+
+ def processReplaceFAEndMsg(self, fields):
+ reqId = decode(int, fields)
+ text = decode(str, fields)
+
+ self.wrapper.replaceFAEnd(reqId, text)
+
+ def processReplaceFAEndMsgProtoBuf(self, protobuf):
+ replaceFAEndProto = ReplaceFAEndProto()
+ replaceFAEndProto.ParseFromString(protobuf)
+
+ self.wrapper.replaceFAEndProtoBuf(replaceFAEndProto)
+
+ reqId = replaceFAEndProto.reqId if replaceFAEndProto.HasField('reqId') else NO_VALID_ID
+ text = replaceFAEndProto.text if replaceFAEndProto.HasField('text') else ""
+
+ self.wrapper.replaceFAEnd(reqId, text)
+
+ def processWshMetaDataMsg(self, fields):
+ reqId = decode(int, fields)
+ dataJson = decode(str, fields)
+
+ self.wrapper.wshMetaData(reqId, dataJson)
+
+ def processWshMetaDataMsgProtoBuf(self, protobuf):
+ wshMetaDataProto = WshMetaDataProto()
+ wshMetaDataProto.ParseFromString(protobuf)
+
+ self.wrapper.wshMetaDataProtoBuf(wshMetaDataProto)
+
+ reqId = wshMetaDataProto.reqId if wshMetaDataProto.HasField('reqId') else NO_VALID_ID
+ dataJson = wshMetaDataProto.dataJson if wshMetaDataProto.HasField('dataJson') else ""
+
+ self.wrapper.wshMetaData(reqId, dataJson)
+
+ def processWshEventDataMsg(self, fields):
+ reqId = decode(int, fields)
+ dataJson = decode(str, fields)
+
+ self.wrapper.wshEventData(reqId, dataJson)
+
+ def processWshEventDataMsgProtoBuf(self, protobuf):
+ wshEventDataProto = WshEventDataProto()
+ wshEventDataProto.ParseFromString(protobuf)
+
+ self.wrapper.wshEventDataProtoBuf(wshEventDataProto)
+
+ reqId = wshEventDataProto.reqId if wshEventDataProto.HasField('reqId') else NO_VALID_ID
+ dataJson = wshEventDataProto.dataJson if wshEventDataProto.HasField('dataJson') else ""
+
+ self.wrapper.wshEventData(reqId, dataJson)
+
+ def processHistoricalSchedule(self, fields):
+ reqId = decode(int, fields)
+ startDateTime = decode(str, fields)
+ endDateTime = decode(str, fields)
+ timeZone = decode(str, fields)
+ sessionsCount = decode(int, fields)
+
+ sessions = []
+
+ for _ in range(sessionsCount):
+ historicalSession = HistoricalSession()
+ historicalSession.startDateTime = decode(str, fields)
+ historicalSession.endDateTime = decode(str, fields)
+ historicalSession.refDate = decode(str, fields)
+ sessions.append(historicalSession)
+
+ self.wrapper.historicalSchedule(
+ reqId, startDateTime, endDateTime, timeZone, sessions
+ )
+
+ def processHistoricalScheduleMsgProtoBuf(self, protobuf):
+ historicalScheduleProto = HistoricalScheduleProto()
+ historicalScheduleProto.ParseFromString(protobuf)
+
+ self.wrapper.historicalScheduleProtoBuf(historicalScheduleProto)
+
+ reqId = historicalScheduleProto.reqId if historicalScheduleProto.HasField('reqId') else NO_VALID_ID
+ startDateTime = historicalScheduleProto.startDateTime if historicalScheduleProto.HasField('startDateTime') else ""
+ endDateTime = historicalScheduleProto.endDateTime if historicalScheduleProto.HasField('endDateTime') else ""
+ timeZone = historicalScheduleProto.timeZone if historicalScheduleProto.HasField('timeZone') else ""
+
+ sessions = []
+ if historicalScheduleProto.historicalSessions:
+ for historicalSessionProto in historicalScheduleProto.historicalSessions:
+ historicalSession = HistoricalSession()
+ historicalSession.startDateTime = historicalSessionProto.startDateTime if historicalSessionProto.HasField('startDateTime') else ""
+ historicalSession.endDateTime = historicalSessionProto.endDateTime if historicalSessionProto.HasField('endDateTime') else ""
+ historicalSession.refDate = historicalSessionProto.refDate if historicalSessionProto.HasField('refDate') else ""
+ sessions.append(historicalSession)
+
+ self.wrapper.historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions)
+
+ def processUserInfo(self, fields):
+ reqId = decode(int, fields)
+ whiteBrandingId = decode(str, fields)
+
+ self.wrapper.userInfo(reqId, whiteBrandingId)
+
+ def processUserInfoMsgProtoBuf(self, protobuf):
+ userInfoProto = UserInfoProto()
+ userInfoProto.ParseFromString(protobuf)
+
+ self.wrapper.userInfoProtoBuf(userInfoProto)
+
+ reqId = userInfoProto.reqId if userInfoProto.HasField('reqId') else NO_VALID_ID
+ whiteBrandingId = userInfoProto.whiteBrandingId if userInfoProto.HasField('whiteBrandingId') else ""
+
+ self.wrapper.userInfo(reqId, whiteBrandingId)
+
+ def processCurrentTimeInMillis(self, fields):
+ timeInMillis = decode(int, fields)
+
+ self.wrapper.currentTimeInMillis(timeInMillis)
+
+ def processCurrentTimeInMillisMsgProtoBuf(self, protobuf):
+ currentTimeInMillisProto = CurrentTimeInMillisProto()
+ currentTimeInMillisProto.ParseFromString(protobuf)
+
+ self.wrapper.currentTimeInMillisProtoBuf(currentTimeInMillisProto)
+
+ timeInMillis = currentTimeInMillisProto.currentTimeInMillis if currentTimeInMillisProto.HasField('currentTimeInMillis') else 0
+
+ self.wrapper.currentTimeInMillis(timeInMillis)
+
+ def processErrorMsg(self, fields):
+ if self.serverVersion < MIN_SERVER_VER_ERROR_TIME:
+ decode(int, fields)
+ reqId = decode(TickerId, fields)
+ errorCode = decode(int, fields)
+ errorString = decode(
+ str, fields, False, self.serverVersion >= MIN_SERVER_VER_ENCODE_MSG_ASCII7
+ )
+ advancedOrderRejectJson = ""
+ if self.serverVersion >= MIN_SERVER_VER_ADVANCED_ORDER_REJECT:
+ advancedOrderRejectJson = decode(str, fields, False, True)
+ errorTime = 0
+ if self.serverVersion >= MIN_SERVER_VER_ERROR_TIME:
+ errorTime = decode(int, fields)
+
+ self.wrapper.error(reqId, errorTime, errorCode, errorString, advancedOrderRejectJson)
+
+ def processErrorMsgProtoBuf(self, protobuf):
+ errorMessageProto = ErrorMessageProto()
+ errorMessageProto.ParseFromString(protobuf)
+
+ self.wrapper.errorProtoBuf(errorMessageProto)
+
+ reqId = errorMessageProto.id if errorMessageProto.HasField('id') else 0
+ errorCode = errorMessageProto.errorCode if errorMessageProto.HasField('errorCode') else 0
+ errorMsg = errorMessageProto.errorMsg if errorMessageProto.HasField('errorMsg') else ""
+ advancedOrderRejectJson = errorMessageProto.advancedOrderRejectJson if errorMessageProto.HasField('advancedOrderRejectJson') else ""
+ errorTime = errorMessageProto.errorTime if errorMessageProto.HasField('errorTime') else 0
+
+ self.wrapper.error(reqId, errorTime, errorCode, errorMsg, advancedOrderRejectJson)
+
+ def processTickStringMsgProtoBuf(self, protobuf):
+ tickStringProto = TickStringProto()
+ tickStringProto.ParseFromString(protobuf)
+
+ self.wrapper.tickStringProtoBuf(tickStringProto)
+
+ reqId = tickStringProto.reqId if tickStringProto.HasField('reqId') else NO_VALID_ID
+ tickType = tickStringProto.tickType if tickStringProto.HasField('tickType') else UNSET_INTEGER
+ value = tickStringProto.value if tickStringProto.HasField('value') else ""
+
+ if tickType != TickTypeEnum.NOT_SET:
+ self.wrapper.tickString(reqId, tickType, value)
+
+ def processTickGenericMsgProtoBuf(self, protobuf):
+ tickGenericProto = TickGenericProto()
+ tickGenericProto.ParseFromString(protobuf)
+
+ self.wrapper.tickGenericProtoBuf(tickGenericProto)
+
+ reqId = tickGenericProto.reqId if tickGenericProto.HasField('reqId') else NO_VALID_ID
+ tickType = tickGenericProto.tickType if tickGenericProto.HasField('tickType') else UNSET_INTEGER
+ value = tickGenericProto.value if tickGenericProto.HasField('value') else UNSET_DOUBLE
+
+ if tickType != TickTypeEnum.NOT_SET:
+ self.wrapper.tickGeneric(reqId, tickType, value)
+
+ def processTickSnapshotEndMsgProtoBuf(self, protobuf):
+ tickSnapshotEndProto = TickSnapshotEndProto()
+ tickSnapshotEndProto.ParseFromString(protobuf)
+
+ self.wrapper.tickSnapshotEndProtoBuf(tickSnapshotEndProto)
+
+ reqId = tickSnapshotEndProto.reqId if tickSnapshotEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.tickSnapshotEnd(reqId)
+
+ def processAccountValueMsgProtoBuf(self, protobuf):
+ accountValueProto = AccountValueProto()
+ accountValueProto.ParseFromString(protobuf)
+
+ self.wrapper.updateAccountValueProtoBuf(accountValueProto)
+
+ key = accountValueProto.key if accountValueProto.HasField('key') else ""
+ value = accountValueProto.value if accountValueProto.HasField('value') else ""
+ currency = accountValueProto.currency if accountValueProto.HasField('currency') else ""
+ accountName = accountValueProto.accountName if accountValueProto.HasField('accountName') else ""
+
+ self.wrapper.updateAccountValue(key, value, currency, accountName)
+
+ def processAcctUpdateTimeMsgProtoBuf(self, protobuf):
+ accountUpdateTimeProto = AccountUpdateTimeProto()
+ accountUpdateTimeProto.ParseFromString(protobuf)
+
+ self.wrapper.updateAccountTimeProtoBuf(accountUpdateTimeProto)
+
+ timeStamp = accountUpdateTimeProto.timeStamp if accountUpdateTimeProto.HasField('timeStamp') else ""
+
+ self.wrapper.updateAccountTime(timeStamp)
+
+ def processAccountDataEndMsgProtoBuf(self, protobuf):
+ accountDataEndProto = AccountDataEndProto()
+ accountDataEndProto.ParseFromString(protobuf)
+
+ self.wrapper.accountDataEndProtoBuf(accountDataEndProto)
+
+ accountName = accountDataEndProto.accountName if accountDataEndProto.HasField('accountName') else ""
+
+ self.wrapper.accountDownloadEnd(accountName)
+
+ def processManagedAccountsMsgProtoBuf(self, protobuf):
+ managedAccountsProto = ManagedAccountsProto()
+ managedAccountsProto.ParseFromString(protobuf)
+
+ self.wrapper.managedAccountsProtoBuf(managedAccountsProto)
+
+ accountsList = managedAccountsProto.accountsList if managedAccountsProto.HasField('accountsList') else ""
+
+ self.wrapper.managedAccounts(accountsList)
+
+ def processPositionEndMsgProtoBuf(self, protobuf):
+ positionEndProto = PositionEndProto()
+ positionEndProto.ParseFromString(protobuf)
+
+ self.wrapper.positionEndProtoBuf(positionEndProto)
+
+ self.wrapper.positionEnd()
+
+ def processAccountSummaryMsgProtoBuf(self, protobuf):
+ accountSummaryProto = AccountSummaryProto()
+ accountSummaryProto.ParseFromString(protobuf)
+
+ self.wrapper.accountSummaryProtoBuf(accountSummaryProto)
+
+ reqId = accountSummaryProto.reqId if accountSummaryProto.HasField('reqId') else NO_VALID_ID
+ account = accountSummaryProto.account if accountSummaryProto.HasField('account') else ""
+ tag = accountSummaryProto.tag if accountSummaryProto.HasField('tag') else ""
+ value = accountSummaryProto.value if accountSummaryProto.HasField('value') else ""
+ currency = accountSummaryProto.currency if accountSummaryProto.HasField('currency') else ""
+
+ self.wrapper.accountSummary(reqId, account, tag, value, currency)
+
+ def processAccountSummaryEndMsgProtoBuf(self, protobuf):
+ accountSummaryEndProto = AccountSummaryEndProto()
+ accountSummaryEndProto.ParseFromString(protobuf)
+
+ self.wrapper.accountSummaryEndProtoBuf(accountSummaryEndProto)
+
+ reqId = accountSummaryEndProto.reqId if accountSummaryEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.accountSummaryEnd(reqId)
+
+ def processPositionMultiEndMsgProtoBuf(self, protobuf):
+ positionMultiEndProto = PositionMultiEndProto()
+ positionMultiEndProto.ParseFromString(protobuf)
+
+ self.wrapper.positionMultiEndProtoBuf(positionMultiEndProto)
+
+ reqId = positionMultiEndProto.reqId if positionMultiEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.positionMultiEnd(reqId)
+
+ def processAccountUpdateMultiMsgProtoBuf(self, protobuf):
+ accountUpdateMultiProto = AccountUpdateMultiProto()
+ accountUpdateMultiProto.ParseFromString(protobuf)
+
+ self.wrapper.accountUpdateMultiProtoBuf(accountUpdateMultiProto)
+
+ reqId = accountUpdateMultiProto.reqId if accountUpdateMultiProto.HasField('reqId') else NO_VALID_ID
+ account = accountUpdateMultiProto.account if accountUpdateMultiProto.HasField('account') else ""
+ modelCode = accountUpdateMultiProto.modelCode if accountUpdateMultiProto.HasField('modelCode') else ""
+ key = accountUpdateMultiProto.key if accountUpdateMultiProto.HasField('key') else ""
+ value = accountUpdateMultiProto.value if accountUpdateMultiProto.HasField('value') else ""
+ currency = accountUpdateMultiProto.currency if accountUpdateMultiProto.HasField('currency') else ""
+
+ self.wrapper.accountUpdateMulti(reqId, account, modelCode, key, value, currency)
+
+ def processAccountUpdateMultiEndMsgProtoBuf(self, protobuf):
+ accountUpdateMultiEndProto = AccountUpdateMultiEndProto()
+ accountUpdateMultiEndProto.ParseFromString(protobuf)
+
+ self.wrapper.accountUpdateMultiEndProtoBuf(accountUpdateMultiEndProto)
+
+ reqId = accountUpdateMultiEndProto.reqId if accountUpdateMultiEndProto.HasField('reqId') else NO_VALID_ID
+
+ self.wrapper.accountUpdateMultiEnd(reqId)
+
+ def processNewsBulletinMsgProtoBuf(self, protobuf):
+ newsBulletinProto = NewsBulletinProto()
+ newsBulletinProto.ParseFromString(protobuf)
+
+ self.wrapper.updateNewsBulletinProtoBuf(newsBulletinProto)
+
+ msgId = newsBulletinProto.newsMsgId if newsBulletinProto.HasField('newsMsgId') else 0
+ msgType = newsBulletinProto.newsMsgType if newsBulletinProto.HasField('newsMsgType') else 0
+ message = newsBulletinProto.newsMessage if newsBulletinProto.HasField('newsMessage') else ""
+ originExch = newsBulletinProto.originatingExch if newsBulletinProto.HasField('originatingExch') else ""
+
+ self.wrapper.updateNewsBulletin(msgId, msgType, message, originExch)
+
+ def processScannerParametersMsgProtoBuf(self, protobuf):
+ scannerParametersProto = ScannerParametersProto()
+ scannerParametersProto.ParseFromString(protobuf)
+
+ self.wrapper.scannerParametersProtoBuf(scannerParametersProto)
+
+ xml = scannerParametersProto.xml if scannerParametersProto.HasField('xml') else ""
+
+ self.wrapper.scannerParameters(xml)
+
+ def processFundamentalsDataMsgProtoBuf(self, protobuf):
+ fundamentalsDataProto = FundamentalsDataProto()
+ fundamentalsDataProto.ParseFromString(protobuf)
+
+ self.wrapper.fundamentalsDataProtoBuf(fundamentalsDataProto)
+
+ reqId = fundamentalsDataProto.reqId if fundamentalsDataProto.HasField('reqId') else NO_VALID_ID
+ data = fundamentalsDataProto.data if fundamentalsDataProto.HasField('data') else ""
+
+ self.wrapper.fundamentalData(reqId, data)
+
+ def processReceiveFAMsgProtoBuf(self, protobuf):
+ receiveFAProto = ReceiveFAProto()
+ receiveFAProto.ParseFromString(protobuf)
+
+ self.wrapper.receiveFAProtoBuf(receiveFAProto)
+
+ faDataType = receiveFAProto.faDataType if receiveFAProto.HasField('faDataType') else 0
+ xml = receiveFAProto.xml if receiveFAProto.HasField('xml') else ""
+
+ self.wrapper.receiveFA(faDataType, xml)
+
+ def processNextValidIdMsgProtoBuf(self, protobuf):
+ nextValidIdProto = NextValidIdProto()
+ nextValidIdProto.ParseFromString(protobuf)
+
+ self.wrapper.nextValidIdProtoBuf(nextValidIdProto)
+
+ orderId = nextValidIdProto.orderId if nextValidIdProto.HasField('orderId') else 0
+
+ self.wrapper.nextValidId(orderId)
+
+ def processCurrentTimeMsgProtoBuf(self, protobuf):
+ currentTimeProto = CurrentTimeProto()
+ currentTimeProto.ParseFromString(protobuf)
+
+ self.wrapper.currentTimeProtoBuf(currentTimeProto)
+
+ time = currentTimeProto.currentTime if currentTimeProto.HasField('currentTime') else 0
+
+ self.wrapper.currentTime(time)
+
+ def processVerifyMessageApiMsgProtoBuf(self, protobuf):
+ verifyMessageApiProto = VerifyMessageApiProto()
+ verifyMessageApiProto.ParseFromString(protobuf)
+
+ self.wrapper.verifyMessageApiProtoBuf(verifyMessageApiProto)
+
+ apiData = verifyMessageApiProto.apiData if verifyMessageApiProto.HasField('apiData') else ""
+
+ self.wrapper.verifyMessageAPI(apiData)
+
+ def processVerifyCompletedMsgProtoBuf(self, protobuf):
+ verifyCompletedProto = VerifyCompletedProto()
+ verifyCompletedProto.ParseFromString(protobuf)
+
+ self.wrapper.verifyCompletedProtoBuf(verifyCompletedProto)
+
+ isSuccessful = verifyCompletedProto.isSuccessful if verifyCompletedProto.HasField('isSuccessful') else False
+ errorText = verifyCompletedProto.errorText if verifyCompletedProto.HasField('errorText') else ""
+
+ self.wrapper.verifyCompleted(isSuccessful, errorText)
+
+ def processDisplayGroupListMsgProtoBuf(self, protobuf):
+ displayGroupListProto = DisplayGroupListProto()
+ displayGroupListProto.ParseFromString(protobuf)
+
+ self.wrapper.displayGroupListProtoBuf(displayGroupListProto)
+
+ reqId = displayGroupListProto.reqId if displayGroupListProto.HasField('reqId') else NO_VALID_ID
+ groups = displayGroupListProto.groups if displayGroupListProto.HasField('groups') else ""
+
+ self.wrapper.displayGroupList(reqId, groups)
+
+ def processDisplayGroupUpdatedMsgProtoBuf(self, protobuf):
+ displayGroupUpdatedProto = DisplayGroupUpdatedProto()
+ displayGroupUpdatedProto.ParseFromString(protobuf)
+
+ self.wrapper.displayGroupUpdatedProtoBuf(displayGroupUpdatedProto)
+
+ reqId = displayGroupUpdatedProto.reqId if displayGroupUpdatedProto.HasField('reqId') else NO_VALID_ID
+ contractInfo = displayGroupUpdatedProto.contractInfo if displayGroupUpdatedProto.HasField('contractInfo') else ""
+
+ self.wrapper.displayGroupUpdated(reqId, contractInfo)
+
+ def processConfigResponseProtoBuf(self, protobuf):
+ configResponseProto = ConfigResponseProto()
+ configResponseProto.ParseFromString(protobuf)
+
+ self.wrapper.configResponseProtoBuf(configResponseProto)
+
+ def processUpdateConfigResponseProtoBuf(self, protobuf):
+ updateConfigResponseProto = UpdateConfigResponseProto()
+ updateConfigResponseProto.ParseFromString(protobuf)
+
+ self.wrapper.updateConfigResponseProtoBuf(updateConfigResponseProto)
+
+ ######################################################################
+
+ def readLastTradeDate(self, fields, contract: ContractDetails, isBond: bool):
+ lastTradeDateOrContractMonth = decode(str, fields)
+ setLastTradeDate(lastTradeDateOrContractMonth, contract, isBond)
+
+ ######################################################################
+
+ def discoverParams(self):
+ meth2handleInfo = {}
+ for handleInfo in self.msgId2handleInfo.values():
+ meth2handleInfo[handleInfo.wrapperMeth] = handleInfo
+
+ methods = inspect.getmembers(EWrapper, inspect.isfunction)
+ for _, meth in methods:
+ # logger.debug("meth %s", name)
+ sig = inspect.signature(meth)
+ handleInfo = meth2handleInfo.get(meth, None)
+ if handleInfo is not None:
+ handleInfo.wrapperParams = sig.parameters
+
+ # for (pname, param) in sig.parameters.items():
+ # logger.debug("\tparam %s %s %s", pname, param.name, param.annotation)
+
+ def printParams(self):
+ for _, handleInfo in self.msgId2handleInfo.items():
+ if handleInfo.wrapperMeth is not None:
+ logger.debug("meth %s", handleInfo.wrapperMeth.__name__)
+ if handleInfo.wrapperParams is not None:
+ for pname, param in handleInfo.wrapperParams.items():
+ logger.debug(
+ "\tparam %s %s %s", pname, param.name, param.annotation
+ )
+
+ def interpretWithSignature(self, fields, handleInfo):
+ if handleInfo.wrapperParams is None:
+ logger.debug("%s: no param info in %s", fields, handleInfo)
+ return
+
+ nIgnoreFields = 1 # bypass msgId faster this way
+ if len(fields) - nIgnoreFields != len(handleInfo.wrapperParams) - 1:
+ logger.error(
+ "diff len fields and params %d %d for fields: %s and handleInfo: %s",
+ len(fields),
+ len(handleInfo.wrapperParams),
+ fields,
+ handleInfo,
+ )
+ return
+
+ fieldIdx = nIgnoreFields
+ args = []
+ for pname, param in handleInfo.wrapperParams.items():
+ if pname != "self":
+ logger.debug("field %s ", fields[fieldIdx])
+ try:
+ arg = fields[fieldIdx].decode(
+ "unicode-escape"
+ if self.serverVersion >= MIN_SERVER_VER_ENCODE_MSG_ASCII7
+ else "UTF-8"
+ )
+ except UnicodeDecodeError:
+ arg = fields[fieldIdx].decode("latin-1")
+ logger.debug("arg %s type %s", arg, param.annotation)
+ if param.annotation is int:
+ arg = int(arg)
+ elif param.annotation is float:
+ arg = float(arg)
+ elif param.annotation is Decimal:
+ if arg is None or len(arg) == 0:
+ return UNSET_DECIMAL
+ else:
+ return Decimal(arg)
+
+ args.append(arg)
+ fieldIdx += 1
+
+ method = getattr(self.wrapper, handleInfo.wrapperMeth.__name__)
+ logger.debug("calling %s with %s %s", method, self.wrapper, args)
+ method(*args)
+
+ def interpret(self, fields, msgId):
+ if msgId == 0:
+ logger.debug("Unset message id:%d", msgId)
+ return
+
+ handleInfo = self.msgId2handleInfo.get(msgId, None)
+
+ if handleInfo is None:
+ logger.debug("msgId:%d - %s: no handleInfo", fields)
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), UNKNOWN_ID.code(), UNKNOWN_ID.msg())
+ return
+
+ try:
+ if handleInfo.wrapperMeth is not None:
+ logger.debug("In interpret(), handleInfo: %s", handleInfo)
+ self.interpretWithSignature(fields, handleInfo)
+ elif handleInfo.processMeth is not None:
+ handleInfo.processMeth(self, iter(fields))
+ except BadMessage:
+ theBadMsg = ",".join(fields)
+ self.wrapper.error(
+ NO_VALID_ID, currentTimeMillis(), BAD_MESSAGE.code(), BAD_MESSAGE.msg() + theBadMsg
+ )
+ raise
+
+ def processProtoBuf(self, protoBuf, msgId):
+ if msgId == 0:
+ logger.debug("Unset message id:%d", msgId)
+ return
+
+ handleInfo = self.msgId2handleInfoProtoBuf.get(msgId, None)
+
+ if handleInfo is None:
+ logger.debug("msgId:%d - %s: no handleInfo for protobuf", msgId, protoBuf)
+ self.wrapper.error(NO_VALID_ID, currentTimeMillis(), UNKNOWN_ID.code(), UNKNOWN_ID.msg())
+ return
+
+ try:
+ if handleInfo.processMeth is not None:
+ handleInfo.processMeth(self, protoBuf)
+ except BadMessage:
+ theBadMsg = repr(protoBuf)
+ self.wrapper.error(
+ NO_VALID_ID, currentTimeMillis(), BAD_MESSAGE.code(), BAD_MESSAGE.msg() + theBadMsg
+ )
+ raise
+
+ msgId2handleInfo = {
+ IN.TICK_PRICE: HandleInfo(proc=processTickPriceMsg),
+ IN.TICK_SIZE: HandleInfo(proc=processTickSizeMsg),
+ IN.ORDER_STATUS: HandleInfo(proc=processOrderStatusMsg),
+ IN.ERR_MSG: HandleInfo(proc=processErrorMsg),
+ IN.OPEN_ORDER: HandleInfo(proc=processOpenOrder),
+ IN.ACCT_VALUE: HandleInfo(wrap=EWrapper.updateAccountValue),
+ IN.PORTFOLIO_VALUE: HandleInfo(proc=processPortfolioValueMsg),
+ IN.ACCT_UPDATE_TIME: HandleInfo(wrap=EWrapper.updateAccountTime),
+ IN.NEXT_VALID_ID: HandleInfo(
+ wrap=EWrapper.nextValidId,
+ ),
+ IN.CONTRACT_DATA: HandleInfo(proc=processContractDataMsg),
+ IN.EXECUTION_DATA: HandleInfo(proc=processExecutionDataMsg),
+ IN.MARKET_DEPTH: HandleInfo(proc=processMarketDepthMsg),
+ IN.MARKET_DEPTH_L2: HandleInfo(proc=processMarketDepthL2Msg),
+ IN.NEWS_BULLETINS: HandleInfo(wrap=EWrapper.updateNewsBulletin),
+ IN.MANAGED_ACCTS: HandleInfo(wrap=EWrapper.managedAccounts),
+ IN.RECEIVE_FA: HandleInfo(wrap=EWrapper.receiveFA),
+ IN.HISTORICAL_DATA: HandleInfo(proc=processHistoricalDataMsg),
+ IN.HISTORICAL_DATA_UPDATE: HandleInfo(proc=processHistoricalDataUpdateMsg),
+ IN.BOND_CONTRACT_DATA: HandleInfo(proc=processBondContractDataMsg),
+ IN.SCANNER_PARAMETERS: HandleInfo(wrap=EWrapper.scannerParameters),
+ IN.SCANNER_DATA: HandleInfo(proc=processScannerDataMsg),
+ IN.TICK_OPTION_COMPUTATION: HandleInfo(proc=processTickOptionComputationMsg),
+ IN.TICK_GENERIC: HandleInfo(wrap=EWrapper.tickGeneric),
+ IN.TICK_STRING: HandleInfo(wrap=EWrapper.tickString),
+ IN.TICK_EFP: HandleInfo(wrap=EWrapper.tickEFP),
+ IN.CURRENT_TIME: HandleInfo(wrap=EWrapper.currentTime),
+ IN.REAL_TIME_BARS: HandleInfo(proc=processRealTimeBarMsg),
+ IN.FUNDAMENTAL_DATA: HandleInfo(wrap=EWrapper.fundamentalData),
+ IN.CONTRACT_DATA_END: HandleInfo(wrap=EWrapper.contractDetailsEnd),
+ IN.OPEN_ORDER_END: HandleInfo(wrap=EWrapper.openOrderEnd),
+ IN.ACCT_DOWNLOAD_END: HandleInfo(wrap=EWrapper.accountDownloadEnd),
+ IN.EXECUTION_DATA_END: HandleInfo(wrap=EWrapper.execDetailsEnd),
+ IN.DELTA_NEUTRAL_VALIDATION: HandleInfo(proc=processDeltaNeutralValidationMsg),
+ IN.TICK_SNAPSHOT_END: HandleInfo(wrap=EWrapper.tickSnapshotEnd),
+ IN.MARKET_DATA_TYPE: HandleInfo(wrap=EWrapper.marketDataType),
+ IN.COMMISSION_AND_FEES_REPORT: HandleInfo(proc=processCommissionAndFeesReportMsg),
+ IN.POSITION_DATA: HandleInfo(proc=processPositionDataMsg),
+ IN.POSITION_END: HandleInfo(wrap=EWrapper.positionEnd),
+ IN.ACCOUNT_SUMMARY: HandleInfo(wrap=EWrapper.accountSummary),
+ IN.ACCOUNT_SUMMARY_END: HandleInfo(wrap=EWrapper.accountSummaryEnd),
+ IN.VERIFY_MESSAGE_API: HandleInfo(wrap=EWrapper.verifyMessageAPI),
+ IN.VERIFY_COMPLETED: HandleInfo(wrap=EWrapper.verifyCompleted),
+ IN.DISPLAY_GROUP_LIST: HandleInfo(wrap=EWrapper.displayGroupList),
+ IN.DISPLAY_GROUP_UPDATED: HandleInfo(wrap=EWrapper.displayGroupUpdated),
+ IN.VERIFY_AND_AUTH_MESSAGE_API: HandleInfo(
+ wrap=EWrapper.verifyAndAuthMessageAPI
+ ),
+ IN.VERIFY_AND_AUTH_COMPLETED: HandleInfo(wrap=EWrapper.verifyAndAuthCompleted),
+ IN.POSITION_MULTI: HandleInfo(proc=processPositionMultiMsg),
+ IN.POSITION_MULTI_END: HandleInfo(wrap=EWrapper.positionMultiEnd),
+ IN.ACCOUNT_UPDATE_MULTI: HandleInfo(wrap=EWrapper.accountUpdateMulti),
+ IN.ACCOUNT_UPDATE_MULTI_END: HandleInfo(wrap=EWrapper.accountUpdateMultiEnd),
+ IN.SECURITY_DEFINITION_OPTION_PARAMETER: HandleInfo(
+ proc=processSecurityDefinitionOptionParameterMsg
+ ),
+ IN.SECURITY_DEFINITION_OPTION_PARAMETER_END: HandleInfo(
+ proc=processSecurityDefinitionOptionParameterEndMsg
+ ),
+ IN.SOFT_DOLLAR_TIERS: HandleInfo(proc=processSoftDollarTiersMsg),
+ IN.FAMILY_CODES: HandleInfo(proc=processFamilyCodesMsg),
+ IN.SYMBOL_SAMPLES: HandleInfo(proc=processSymbolSamplesMsg),
+ IN.SMART_COMPONENTS: HandleInfo(proc=processSmartComponents),
+ IN.TICK_REQ_PARAMS: HandleInfo(proc=processTickReqParams),
+ IN.MKT_DEPTH_EXCHANGES: HandleInfo(proc=processMktDepthExchanges),
+ IN.HEAD_TIMESTAMP: HandleInfo(proc=processHeadTimestamp),
+ IN.TICK_NEWS: HandleInfo(proc=processTickNews),
+ IN.NEWS_PROVIDERS: HandleInfo(proc=processNewsProviders),
+ IN.NEWS_ARTICLE: HandleInfo(proc=processNewsArticle),
+ IN.HISTORICAL_NEWS: HandleInfo(proc=processHistoricalNews),
+ IN.HISTORICAL_NEWS_END: HandleInfo(proc=processHistoricalNewsEnd),
+ IN.HISTOGRAM_DATA: HandleInfo(proc=processHistogramData),
+ IN.REROUTE_MKT_DATA_REQ: HandleInfo(proc=processRerouteMktDataReq),
+ IN.REROUTE_MKT_DEPTH_REQ: HandleInfo(proc=processRerouteMktDepthReq),
+ IN.MARKET_RULE: HandleInfo(proc=processMarketRuleMsg),
+ IN.PNL: HandleInfo(proc=processPnLMsg),
+ IN.PNL_SINGLE: HandleInfo(proc=processPnLSingleMsg),
+ IN.HISTORICAL_TICKS: HandleInfo(proc=processHistoricalTicks),
+ IN.HISTORICAL_TICKS_BID_ASK: HandleInfo(proc=processHistoricalTicksBidAsk),
+ IN.HISTORICAL_TICKS_LAST: HandleInfo(proc=processHistoricalTicksLast),
+ IN.TICK_BY_TICK: HandleInfo(proc=processTickByTickMsg),
+ IN.ORDER_BOUND: HandleInfo(proc=processOrderBoundMsg),
+ IN.COMPLETED_ORDER: HandleInfo(proc=processCompletedOrderMsg),
+ IN.COMPLETED_ORDERS_END: HandleInfo(proc=processCompletedOrdersEndMsg),
+ IN.REPLACE_FA_END: HandleInfo(proc=processReplaceFAEndMsg),
+ IN.WSH_META_DATA: HandleInfo(proc=processWshMetaDataMsg),
+ IN.WSH_EVENT_DATA: HandleInfo(proc=processWshEventDataMsg),
+ IN.HISTORICAL_SCHEDULE: HandleInfo(proc=processHistoricalSchedule),
+ IN.USER_INFO: HandleInfo(proc=processUserInfo),
+ IN.HISTORICAL_DATA_END: HandleInfo(proc=processHistoricalDataEndMsg),
+ IN.CURRENT_TIME_IN_MILLIS: HandleInfo(proc=processCurrentTimeInMillis),
+ }
+
+ msgId2handleInfoProtoBuf = {
+ IN.ORDER_STATUS: HandleInfo(proc=processOrderStatusMsgProtoBuf),
+ IN.ERR_MSG: HandleInfo(proc=processErrorMsgProtoBuf),
+ IN.OPEN_ORDER: HandleInfo(proc=processOpenOrderMsgProtoBuf),
+ IN.EXECUTION_DATA: HandleInfo(proc=processExecutionDataMsgProtoBuf),
+ IN.OPEN_ORDER_END: HandleInfo(proc=processOpenOrdersEndMsgProtoBuf),
+ IN.EXECUTION_DATA_END: HandleInfo(proc=processExecutionDataEndMsgProtoBuf),
+ IN.COMPLETED_ORDER: HandleInfo(proc=processCompletedOrderMsgProtoBuf),
+ IN.COMPLETED_ORDERS_END: HandleInfo(proc=processCompletedOrdersEndMsgProtoBuf),
+ IN.ORDER_BOUND: HandleInfo(proc=processOrderBoundMsgProtoBuf),
+ IN.CONTRACT_DATA: HandleInfo(proc=processContractDataMsgProtoBuf),
+ IN.BOND_CONTRACT_DATA: HandleInfo(proc=processBondContractDataMsgProtoBuf),
+ IN.CONTRACT_DATA_END: HandleInfo(proc=processContractDataEndMsgProtoBuf),
+ IN.TICK_PRICE: HandleInfo(proc=processTickPriceMsgProtoBuf),
+ IN.TICK_SIZE: HandleInfo(proc=processTickSizeMsgProtoBuf),
+ IN.TICK_OPTION_COMPUTATION: HandleInfo(proc=processTickOptionComputationMsgProtoBuf),
+ IN.TICK_GENERIC: HandleInfo(proc=processTickGenericMsgProtoBuf),
+ IN.TICK_STRING: HandleInfo(proc=processTickStringMsgProtoBuf),
+ IN.TICK_SNAPSHOT_END: HandleInfo(proc=processTickSnapshotEndMsgProtoBuf),
+ IN.MARKET_DEPTH: HandleInfo(proc=processMarketDepthMsgProtoBuf),
+ IN.MARKET_DEPTH_L2: HandleInfo(proc=processMarketDepthL2MsgProtoBuf),
+ IN.MARKET_DATA_TYPE: HandleInfo(proc=processMarketDataTypeMsgProtoBuf),
+ IN.TICK_REQ_PARAMS: HandleInfo(proc=processTickReqParamsMsgProtoBuf),
+ IN.ACCT_VALUE: HandleInfo(proc=processAccountValueMsgProtoBuf),
+ IN.PORTFOLIO_VALUE: HandleInfo(proc=processPortfolioValueMsgProtoBuf),
+ IN.ACCT_UPDATE_TIME: HandleInfo(proc=processAcctUpdateTimeMsgProtoBuf),
+ IN.ACCT_DOWNLOAD_END: HandleInfo(proc=processAccountDataEndMsgProtoBuf),
+ IN.MANAGED_ACCTS: HandleInfo(proc=processManagedAccountsMsgProtoBuf),
+ IN.POSITION_DATA: HandleInfo(proc=processPositionMsgProtoBuf),
+ IN.POSITION_END: HandleInfo(proc=processPositionEndMsgProtoBuf),
+ IN.ACCOUNT_SUMMARY: HandleInfo(proc=processAccountSummaryMsgProtoBuf),
+ IN.ACCOUNT_SUMMARY_END: HandleInfo(proc=processAccountSummaryEndMsgProtoBuf),
+ IN.POSITION_MULTI: HandleInfo(proc=processPositionMultiMsgProtoBuf),
+ IN.POSITION_MULTI_END: HandleInfo(proc=processPositionMultiEndMsgProtoBuf),
+ IN.ACCOUNT_UPDATE_MULTI: HandleInfo(proc=processAccountUpdateMultiMsgProtoBuf),
+ IN.ACCOUNT_UPDATE_MULTI_END: HandleInfo(proc=processAccountUpdateMultiEndMsgProtoBuf),
+ IN.HISTORICAL_DATA: HandleInfo(proc=processHistoricalDataMsgProtoBuf),
+ IN.HISTORICAL_DATA_UPDATE: HandleInfo(proc=processHistoricalDataUpdateMsgProtoBuf),
+ IN.HISTORICAL_DATA_END: HandleInfo(proc=processHistoricalDataEndMsgProtoBuf),
+ IN.REAL_TIME_BARS: HandleInfo(proc=processRealTimeBarMsgProtoBuf),
+ IN.HEAD_TIMESTAMP: HandleInfo(proc=processHeadTimestampMsgProtoBuf),
+ IN.HISTOGRAM_DATA: HandleInfo(proc=processHistogramDataMsgProtoBuf),
+ IN.HISTORICAL_TICKS: HandleInfo(proc=processHistoricalTicksMsgProtoBuf),
+ IN.HISTORICAL_TICKS_BID_ASK: HandleInfo(proc=processHistoricalTicksBidAskMsgProtoBuf),
+ IN.HISTORICAL_TICKS_LAST: HandleInfo(proc=processHistoricalTicksLastMsgProtoBuf),
+ IN.TICK_BY_TICK: HandleInfo(proc=processTickByTickMsgProtoBuf),
+ IN.NEWS_BULLETINS: HandleInfo(proc=processNewsBulletinMsgProtoBuf),
+ IN.NEWS_ARTICLE: HandleInfo(proc=processNewsArticleMsgProtoBuf),
+ IN.NEWS_PROVIDERS: HandleInfo(proc=processNewsProvidersMsgProtoBuf),
+ IN.HISTORICAL_NEWS: HandleInfo(proc=processHistoricalNewsMsgProtoBuf),
+ IN.HISTORICAL_NEWS_END: HandleInfo(proc=processHistoricalNewsEndMsgProtoBuf),
+ IN.WSH_META_DATA: HandleInfo(proc=processWshMetaDataMsgProtoBuf),
+ IN.WSH_EVENT_DATA: HandleInfo(proc=processWshEventDataMsgProtoBuf),
+ IN.TICK_NEWS: HandleInfo(proc=processTickNewsMsgProtoBuf),
+ IN.SCANNER_PARAMETERS: HandleInfo(proc=processScannerParametersMsgProtoBuf),
+ IN.SCANNER_DATA: HandleInfo(proc=processScannerDataMsgProtoBuf),
+ IN.FUNDAMENTAL_DATA: HandleInfo(proc=processFundamentalsDataMsgProtoBuf),
+ IN.PNL: HandleInfo(proc=processPnLMsgProtoBuf),
+ IN.PNL_SINGLE: HandleInfo(proc=processPnLSingleMsgProtoBuf),
+ IN.RECEIVE_FA: HandleInfo(proc=processReceiveFAMsgProtoBuf),
+ IN.REPLACE_FA_END: HandleInfo(proc=processReplaceFAEndMsgProtoBuf),
+ IN.COMMISSION_AND_FEES_REPORT: HandleInfo(proc=processCommissionAndFeesReportMsgProtoBuf),
+ IN.HISTORICAL_SCHEDULE: HandleInfo(proc=processHistoricalScheduleMsgProtoBuf),
+ IN.REROUTE_MKT_DATA_REQ: HandleInfo(proc=processRerouteMktDataReqMsgProtoBuf),
+ IN.REROUTE_MKT_DEPTH_REQ: HandleInfo(proc=processRerouteMktDepthReqMsgProtoBuf),
+ IN.SECURITY_DEFINITION_OPTION_PARAMETER: HandleInfo(proc=processSecurityDefinitionOptionParameterMsgProtoBuf),
+ IN.SECURITY_DEFINITION_OPTION_PARAMETER_END: HandleInfo(proc=processSecurityDefinitionOptionParameterEndMsgProtoBuf),
+ IN.SOFT_DOLLAR_TIERS: HandleInfo(proc=processSoftDollarTiersMsgProtoBuf),
+ IN.FAMILY_CODES: HandleInfo(proc=processFamilyCodesMsgProtoBuf),
+ IN.SYMBOL_SAMPLES: HandleInfo(proc=processSymbolSamplesMsgProtoBuf),
+ IN.SMART_COMPONENTS: HandleInfo(proc=processSmartComponentsMsgProtoBuf),
+ IN.MARKET_RULE: HandleInfo(proc=processMarketRuleMsgProtoBuf),
+ IN.USER_INFO: HandleInfo(proc=processUserInfoMsgProtoBuf),
+ IN.NEXT_VALID_ID: HandleInfo(proc=processNextValidIdMsgProtoBuf),
+ IN.CURRENT_TIME: HandleInfo(proc=processCurrentTimeMsgProtoBuf),
+ IN.CURRENT_TIME_IN_MILLIS: HandleInfo(proc=processCurrentTimeInMillisMsgProtoBuf),
+ IN.VERIFY_MESSAGE_API: HandleInfo(proc=processVerifyMessageApiMsgProtoBuf),
+ IN.VERIFY_COMPLETED: HandleInfo(proc=processVerifyCompletedMsgProtoBuf),
+ IN.DISPLAY_GROUP_LIST: HandleInfo(proc=processDisplayGroupListMsgProtoBuf),
+ IN.DISPLAY_GROUP_UPDATED: HandleInfo(proc=processDisplayGroupUpdatedMsgProtoBuf),
+ IN.MKT_DEPTH_EXCHANGES: HandleInfo(proc=processMktDepthExchangesMsgProtoBuf),
+ IN.CONFIG_RESPONSE: HandleInfo(proc=processConfigResponseProtoBuf),
+ IN.UPDATE_CONFIG_RESPONSE: HandleInfo(proc=processUpdateConfigResponseProtoBuf)
+ }
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/decoder_utils.py b/packages/ibkr/ref/source/pythonclient/ibapi/decoder_utils.py
new file mode 100644
index 00000000..a48774b2
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/decoder_utils.py
@@ -0,0 +1,679 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+from decimal import Decimal
+
+from ibapi.contract import ComboLeg, Contract, DeltaNeutralContract, ContractDetails
+from ibapi.execution import Execution, OptionExerciseType
+from ibapi.order import Order, OrderComboLeg
+from ibapi.order_condition import OrderCondition, OperatorCondition, ContractCondition, PriceCondition, TimeCondition, MarginCondition, ExecutionCondition, VolumeCondition, PercentChangeCondition
+from ibapi.order_state import OrderState, OrderAllocation
+from ibapi.softdollartier import SoftDollarTier
+from ibapi.tag_value import TagValue
+from ibapi.ineligibility_reason import IneligibilityReason
+from ibapi.utils import floatMaxString, getEnumTypeFromString, decimalMaxString, isValidIntValue
+from ibapi.contract import FundDistributionPolicyIndicator
+from ibapi.contract import FundAssetType
+from ibapi.common import BarData, HistogramData, TickAttribBidAsk, TickAttribLast, HistoricalTick, HistoricalTickBidAsk, HistoricalTickLast, FamilyCode, PriceIncrement, SmartComponent, SmartComponentMap, DepthMktDataDescription
+
+from ibapi.protobuf.Contract_pb2 import Contract as ContractProto
+from ibapi.protobuf.DeltaNeutralContract_pb2 import DeltaNeutralContract as DeltaNeutralContractProto
+from ibapi.protobuf.Execution_pb2 import Execution as ExecutionProto
+from ibapi.protobuf.Order_pb2 import Order as OrderProto
+from ibapi.protobuf.OrderCondition_pb2 import OrderCondition as OrderConditionProto
+from ibapi.protobuf.OrderState_pb2 import OrderState as OrderStateProto
+from ibapi.protobuf.OrderAllocation_pb2 import OrderAllocation as OrderAllocatiionProto
+from ibapi.protobuf.SoftDollarTier_pb2 import SoftDollarTier as SoftDollarTierProto
+from ibapi.protobuf.ContractDetails_pb2 import ContractDetails as ContractDetailsProto
+from ibapi.protobuf.HistoricalTick_pb2 import HistoricalTick as HistoricalTickProto
+from ibapi.protobuf.HistoricalTickBidAsk_pb2 import HistoricalTickBidAsk as HistoricalTickBidAskProto
+from ibapi.protobuf.HistoricalTickLast_pb2 import HistoricalTickLast as HistoricalTickLastProto
+from ibapi.protobuf.HistogramDataEntry_pb2 import HistogramDataEntry as HistogramDataEntryProto
+from ibapi.protobuf.HistoricalDataBar_pb2 import HistoricalDataBar as HistoricalDataBarProto
+from ibapi.protobuf.FamilyCode_pb2 import FamilyCode as FamilyCodeProto
+from ibapi.protobuf.SmartComponents_pb2 import SmartComponents as SmartComponentsProto
+from ibapi.protobuf.SmartComponent_pb2 import SmartComponent as SmartComponentProto
+from ibapi.protobuf.PriceIncrement_pb2 import PriceIncrement as PriceIncrementProto
+from ibapi.protobuf.DepthMarketDataDescription_pb2 import DepthMarketDataDescription as DepthMarketDataDescriptionProto
+
+@staticmethod
+def decodeContract(contractProto: ContractProto) -> Contract:
+ contract = Contract()
+ if contractProto.HasField('conId'): contract.conId = contractProto.conId
+ if contractProto.HasField('symbol'): contract.symbol = contractProto.symbol
+ if contractProto.HasField('secType'): contract.secType = contractProto.secType
+ if contractProto.HasField('lastTradeDateOrContractMonth'): contract.lastTradeDateOrContractMonth = contractProto.lastTradeDateOrContractMonth
+ if contractProto.HasField('strike'): contract.strike = contractProto.strike
+ if contractProto.HasField('right'): contract.right = contractProto.right
+ if contractProto.HasField('multiplier'): contract.multiplier = floatMaxString(contractProto.multiplier)
+ if contractProto.HasField('exchange'): contract.exchange = contractProto.exchange
+ if contractProto.HasField('currency'): contract.currency = contractProto.currency
+ if contractProto.HasField('localSymbol'): contract.localSymbol = contractProto.localSymbol
+ if contractProto.HasField('tradingClass'): contract.tradingClass = contractProto.tradingClass
+ if contractProto.HasField('comboLegsDescrip'): contract.comboLegsDescrip = contractProto.comboLegsDescrip
+
+ comboLegs = decodeComboLegs(contractProto)
+ if comboLegs is not None and comboLegs: contract.comboLegs = comboLegs
+
+ deltaNeutralContract = decodeDeltaNeutralContract(contractProto)
+ if deltaNeutralContract is not None: contract.deltaNeutralContract = deltaNeutralContract
+
+ if contractProto.HasField('lastTradeDate'): contract.lastTradeDate = contractProto.lastTradeDate
+ if contractProto.HasField('primaryExch'): contract.primaryExchange = contractProto.primaryExch
+ if contractProto.HasField('issuerId'): contract.issuerId = contractProto.issuerId
+ if contractProto.HasField('description'): contract.description = contractProto.description
+
+ return contract
+
+@staticmethod
+def decodeComboLegs(contractProto: ContractProto) -> list[ComboLeg]:
+ comboLegs = []
+ comboLegProtoList = contractProto.comboLegs
+ if comboLegProtoList:
+ for comboLegProto in comboLegProtoList:
+ comboLeg = ComboLeg()
+ if comboLegProto.HasField('conId'): comboLeg.conId = comboLegProto.conId
+ if comboLegProto.HasField('ratio'): comboLeg.ratio = comboLegProto.ratio
+ if comboLegProto.HasField('action'): comboLeg.action = comboLegProto.action
+ if comboLegProto.HasField('exchange'): comboLeg.exchange = comboLegProto.exchange
+ if comboLegProto.HasField('openClose'): comboLeg.openClose = comboLegProto.openClose
+ if comboLegProto.HasField('shortSalesSlot'): comboLeg.shortSaleSlot = comboLegProto.shortSalesSlot
+ if comboLegProto.HasField('designatedLocation'): comboLeg.designatedLocation = comboLegProto.designatedLocation
+ if comboLegProto.HasField('exemptCode'): comboLeg.exemptCode = comboLegProto.exemptCode
+ comboLegs.append(comboLeg)
+
+ return comboLegs
+
+@staticmethod
+def decodeOrderComboLegs(contractProto: ContractProto) -> list[OrderComboLeg]:
+ orderComboLegs = []
+ comboLegProtoList = contractProto.comboLegs
+ if comboLegProtoList:
+ for comboLegProto in comboLegProtoList:
+ orderComboLeg = OrderComboLeg()
+ if comboLegProto.HasField('perLegPrice'): orderComboLeg.price = comboLegProto.perLegPrice
+ orderComboLegs.append(orderComboLeg)
+
+ return orderComboLegs
+
+@staticmethod
+def decodeDeltaNeutralContract(contractProto: ContractProto) -> DeltaNeutralContract:
+ deltaNeutralContract = None
+ if contractProto.HasField('deltaNeutralContract'):
+ deltaNeutralContractProto = DeltaNeutralContractProto()
+ deltaNeutralContractProto.CopyFrom(contractProto.deltaNeutralContract)
+ if deltaNeutralContractProto is not None:
+ deltaNeutralContract = DeltaNeutralContract()
+ if (deltaNeutralContractProto.HasField('conId')): deltaNeutralContract.conId = deltaNeutralContractProto.conId
+ if (deltaNeutralContractProto.HasField('delta')): deltaNeutralContract.delta = deltaNeutralContractProto.delta
+ if (deltaNeutralContractProto.HasField('price')): deltaNeutralContract.price = deltaNeutralContractProto.price
+
+ return deltaNeutralContract
+
+@staticmethod
+def decodeExecution(executionProto: ExecutionProto) -> Execution:
+ execution = Execution()
+ if executionProto.HasField('orderId'): execution.orderId = executionProto.orderId
+ if executionProto.HasField('clientId'): execution.clientId = executionProto.clientId
+ if executionProto.HasField('execId'): execution.execId = executionProto.execId
+ if executionProto.HasField('time'): execution.time = executionProto.time
+ if executionProto.HasField('acctNumber'): execution.acctNumber = executionProto.acctNumber
+ if executionProto.HasField('exchange'): execution.exchange = executionProto.exchange
+ if executionProto.HasField('side'): execution.side = executionProto.side
+ if executionProto.HasField('shares'): execution.shares = Decimal(executionProto.shares)
+ if executionProto.HasField('price'): execution.price = executionProto.price
+ if executionProto.HasField('permId'): execution.permId = executionProto.permId
+ if executionProto.HasField('isLiquidation'): execution.liquidation = 1 if executionProto.isLiquidation else 0
+ if executionProto.HasField('cumQty'): execution.cumQty = Decimal(executionProto.cumQty)
+ if executionProto.HasField('avgPrice'): execution.avgPrice = executionProto.avgPrice
+ if executionProto.HasField('orderRef'): execution.orderRef = executionProto.orderRef
+ if executionProto.HasField('evRule'): execution.evRule = executionProto.evRule
+ if executionProto.HasField('evMultiplier'): execution.evMultiplier = executionProto.evMultiplier
+ if executionProto.HasField('modelCode'): execution.modelCode = executionProto.modelCode
+ if executionProto.HasField('lastLiquidity'): execution.lastLiquidity = executionProto.lastLiquidity
+ if executionProto.HasField('isPriceRevisionPending'): execution.pendingPriceRevision = executionProto.isPriceRevisionPending
+ if executionProto.HasField('submitter'): execution.submitter = executionProto.submitter
+ if executionProto.HasField('optExerciseOrLapseType'): execution.optExerciseOrLapseType = getEnumTypeFromString(OptionExerciseType, executionProto.optExerciseOrLapseType)
+ return execution
+
+@staticmethod
+def decodeOrder(orderId: int, contractProto: ContractProto, orderProto: OrderProto) -> Order:
+ order = Order()
+ if isValidIntValue(orderId): order.orderId = orderId
+ if orderProto.HasField('orderId'): order.orderId = orderProto.orderId
+ if orderProto.HasField('action'): order.action = orderProto.action
+ if orderProto.HasField('totalQuantity'): order.totalQuantity = Decimal(orderProto.totalQuantity)
+ if orderProto.HasField('orderType'): order.orderType = orderProto.orderType
+ if orderProto.HasField('lmtPrice'): order.lmtPrice = orderProto.lmtPrice
+ if orderProto.HasField('auxPrice'): order.auxPrice = orderProto.auxPrice
+ if orderProto.HasField('tif'): order.tif = orderProto.tif
+ if orderProto.HasField('ocaGroup'): order.ocaGroup = orderProto.ocaGroup
+ if orderProto.HasField('account'): order.account = orderProto.account
+ if orderProto.HasField('openClose'): order.openClose = orderProto.openClose
+ if orderProto.HasField('origin'): order.origin = orderProto.origin
+ if orderProto.HasField('orderRef'): order.orderRef = orderProto.orderRef
+ if orderProto.HasField('clientId'): order.clientId = orderProto.clientId
+ if orderProto.HasField('permId'): order.permId = orderProto.permId
+ if orderProto.HasField('outsideRth'): order.outsideRth = orderProto.outsideRth
+ if orderProto.HasField('hidden'): order.hidden = orderProto.hidden
+ if orderProto.HasField('discretionaryAmt'): order.discretionaryAmt = orderProto.discretionaryAmt
+ if orderProto.HasField('goodAfterTime'): order.goodAfterTime = orderProto.goodAfterTime
+ if orderProto.HasField('faGroup'): order.faGroup = orderProto.faGroup
+ if orderProto.HasField('faMethod'): order.faMethod = orderProto.faMethod
+ if orderProto.HasField('faPercentage'): order.faPercentage = orderProto.faPercentage
+ if orderProto.HasField('modelCode'): order.modelCode = orderProto.modelCode
+ if orderProto.HasField('goodTillDate'): order.goodTillDate = orderProto.goodTillDate
+ if orderProto.HasField('rule80A'): order.rule80A = orderProto.rule80A
+ if orderProto.HasField('percentOffset'): order.percentOffset = orderProto.percentOffset
+ if orderProto.HasField('settlingFirm'): order.settlingFirm = orderProto.settlingFirm
+ if orderProto.HasField('shortSaleSlot'): order.shortSaleSlot = orderProto.shortSaleSlot
+ if orderProto.HasField('designatedLocation'): order.designatedLocation = orderProto.designatedLocation
+ if orderProto.HasField('exemptCode'): order.exemptCode = orderProto.exemptCode
+ if orderProto.HasField('startingPrice'): order.startingPrice = orderProto.startingPrice
+ if orderProto.HasField('stockRefPrice'): order.stockRefPrice = orderProto.stockRefPrice
+ if orderProto.HasField('delta'): order.delta = orderProto.delta
+ if orderProto.HasField('stockRangeLower'): order.stockRangeLower = orderProto.stockRangeLower
+ if orderProto.HasField('stockRangeUpper'): order.stockRangeUpper = orderProto.stockRangeUpper
+ if orderProto.HasField('displaySize'): order.displaySize = orderProto.displaySize
+ if orderProto.HasField('blockOrder'): order.blockOrder = orderProto.blockOrder
+ if orderProto.HasField('sweepToFill'): order.sweepToFill = orderProto.sweepToFill
+ if orderProto.HasField('allOrNone'): order.allOrNone = orderProto.allOrNone
+ if orderProto.HasField('minQty'): order.minQty = orderProto.minQty
+ if orderProto.HasField('ocaType'): order.ocaType = orderProto.ocaType
+ if orderProto.HasField('parentId'): order.parentId = orderProto.parentId
+ if orderProto.HasField('triggerMethod'): order.triggerMethod = orderProto.triggerMethod
+ if orderProto.HasField('volatility'): order.volatility = orderProto.volatility
+ if orderProto.HasField('volatilityType'): order.volatilityType = orderProto.volatilityType
+ if orderProto.HasField('deltaNeutralOrderType'): order.deltaNeutralOrderType = orderProto.deltaNeutralOrderType
+ if orderProto.HasField('deltaNeutralAuxPrice'): order.deltaNeutralAuxPrice = orderProto.deltaNeutralAuxPrice
+ if orderProto.HasField('deltaNeutralConId'): order.deltaNeutralConId = orderProto.deltaNeutralConId
+ if orderProto.HasField('deltaNeutralSettlingFirm'): order.deltaNeutralSettlingFirm = orderProto.deltaNeutralSettlingFirm
+ if orderProto.HasField('deltaNeutralClearingAccount'): order.deltaNeutralClearingAccount = orderProto.deltaNeutralClearingAccount
+ if orderProto.HasField('deltaNeutralClearingIntent'): order.deltaNeutralClearingIntent = orderProto.deltaNeutralClearingIntent
+ if orderProto.HasField('deltaNeutralOpenClose'): order.deltaNeutralOpenClose = orderProto.deltaNeutralOpenClose
+ if orderProto.HasField('deltaNeutralShortSale'): order.deltaNeutralShortSale = orderProto.deltaNeutralShortSale
+ if orderProto.HasField('deltaNeutralShortSaleSlot'): order.deltaNeutralShortSaleSlot = orderProto.deltaNeutralShortSaleSlot
+ if orderProto.HasField('deltaNeutralDesignatedLocation'): order.deltaNeutralDesignatedLocation = orderProto.deltaNeutralDesignatedLocation
+ if orderProto.HasField('continuousUpdate'): order.continuousUpdate = orderProto.continuousUpdate
+ if orderProto.HasField('referencePriceType'): order.referencePriceType = orderProto.referencePriceType
+ if orderProto.HasField('trailStopPrice'): order.trailStopPrice = orderProto.trailStopPrice
+ if orderProto.HasField('trailingPercent'): order.trailingPercent = orderProto.trailingPercent
+
+ orderComboLegs = decodeOrderComboLegs(contractProto)
+ if orderComboLegs is not None and orderComboLegs: order.orderComboLegs = orderComboLegs
+
+ order.smartComboRoutingParams = decodeTagValueList(orderProto.smartComboRoutingParams)
+
+ if orderProto.HasField('scaleInitLevelSize'): order.scaleInitLevelSize = orderProto.scaleInitLevelSize
+ if orderProto.HasField('scaleSubsLevelSize'): order.scaleSubsLevelSize = orderProto.scaleSubsLevelSize
+ if orderProto.HasField('scalePriceIncrement'): order.scalePriceIncrement = orderProto.scalePriceIncrement
+ if orderProto.HasField('scalePriceAdjustValue'): order.scalePriceAdjustValue = orderProto.scalePriceAdjustValue
+ if orderProto.HasField('scalePriceAdjustInterval'): order.scalePriceAdjustInterval = orderProto.scalePriceAdjustInterval
+ if orderProto.HasField('scaleProfitOffset'): order.scaleProfitOffset = orderProto.scaleProfitOffset
+ if orderProto.HasField('scaleAutoReset'): order.scaleAutoReset = orderProto.scaleAutoReset
+ if orderProto.HasField('scaleInitPosition'): order.scaleInitPosition = orderProto.scaleInitPosition
+ if orderProto.HasField('scaleInitFillQty'): order.scaleInitFillQty = orderProto.scaleInitFillQty
+ if orderProto.HasField('scaleRandomPercent'): order.scaleRandomPercent = orderProto.scaleRandomPercent
+ if orderProto.HasField('hedgeType'): order.hedgeType = orderProto.hedgeType
+ if orderProto.HasField('hedgeType') and orderProto.HasField('hedgeParam') and orderProto.hedgeType: order.hedgeParam = orderProto.hedgeParam
+ if orderProto.HasField('optOutSmartRouting'): order.optOutSmartRouting = orderProto.optOutSmartRouting
+ if orderProto.HasField('clearingAccount'): order.clearingAccount = orderProto.clearingAccount
+ if orderProto.HasField('clearingIntent'): order.clearingIntent = orderProto.clearingIntent
+ if orderProto.HasField('notHeld'): order.notHeld = orderProto.notHeld
+
+ if orderProto.HasField('algoStrategy'):
+ order.algoStrategy = orderProto.algoStrategy
+ order.algoParams = decodeTagValueList(orderProto.algoParams)
+
+ if orderProto.HasField('solicited'): order.solicited = orderProto.solicited
+ if orderProto.HasField('whatIf'): order.whatIf = orderProto.whatIf
+ if orderProto.HasField('randomizeSize'): order.randomizeSize = orderProto.randomizeSize
+ if orderProto.HasField('randomizePrice'): order.randomizePrice = orderProto.randomizePrice
+ if orderProto.HasField('referenceContractId'): order.referenceContractId = orderProto.referenceContractId
+ if orderProto.HasField('isPeggedChangeAmountDecrease'): order.isPeggedChangeAmountDecrease = orderProto.isPeggedChangeAmountDecrease
+ if orderProto.HasField('peggedChangeAmount'): order.peggedChangeAmount = orderProto.peggedChangeAmount
+ if orderProto.HasField('referenceChangeAmount'): order.referenceChangeAmount = orderProto.referenceChangeAmount
+ if orderProto.HasField('referenceExchangeId'): order.referenceExchangeId = orderProto.referenceExchangeId
+
+ conditions = decodeConditions(orderProto)
+ if conditions is not None and conditions: order.conditions = conditions
+ if orderProto.HasField('conditionsIgnoreRth'): order.conditionsIgnoreRth = orderProto.conditionsIgnoreRth
+ if orderProto.HasField('conditionsCancelOrder'): order.conditionsCancelOrder = orderProto.conditionsCancelOrder
+
+ if orderProto.HasField('adjustedOrderType'): order.adjustedOrderType = orderProto.adjustedOrderType
+ if orderProto.HasField('triggerPrice'): order.triggerPrice = orderProto.triggerPrice
+ if orderProto.HasField('lmtPriceOffset'): order.lmtPriceOffset = orderProto.lmtPriceOffset
+ if orderProto.HasField('adjustedStopPrice'): order.adjustedStopPrice = orderProto.adjustedStopPrice
+ if orderProto.HasField('adjustedStopLimitPrice'): order.adjustedStopLimitPrice = orderProto.adjustedStopLimitPrice
+ if orderProto.HasField('adjustedTrailingAmount'): order.adjustedTrailingAmount = orderProto.adjustedTrailingAmount
+ if orderProto.HasField('adjustableTrailingUnit'): order.adjustableTrailingUnit = orderProto.adjustableTrailingUnit
+
+ softDollarTier = decodeSoftDollarTierFromOrder(orderProto)
+ if softDollarTier is not None: order.softDollarTier = softDollarTier
+
+ if orderProto.HasField('cashQty'): order.cashQty = orderProto.cashQty
+ if orderProto.HasField('dontUseAutoPriceForHedge'): order.dontUseAutoPriceForHedge = orderProto.dontUseAutoPriceForHedge
+ if orderProto.HasField('isOmsContainer'): order.isOmsContainer = orderProto.isOmsContainer
+ if orderProto.HasField('discretionaryUpToLimitPrice'): order.discretionaryUpToLimitPrice = orderProto.discretionaryUpToLimitPrice
+ if orderProto.HasField('usePriceMgmtAlgo'): order.usePriceMgmtAlgo = orderProto.usePriceMgmtAlgo
+ if orderProto.HasField('duration'): order.duration = orderProto.duration
+ if orderProto.HasField('postToAts'): order.postToAts = orderProto.postToAts
+ if orderProto.HasField('autoCancelParent'): order.autoCancelParent = orderProto.autoCancelParent
+ if orderProto.HasField('minTradeQty'): order.minTradeQty = orderProto.minTradeQty
+ if orderProto.HasField('minCompeteSize'): order.minCompeteSize = orderProto.minCompeteSize
+ if orderProto.HasField('competeAgainstBestOffset'): order.competeAgainstBestOffset = orderProto.competeAgainstBestOffset
+ if orderProto.HasField('midOffsetAtWhole'): order.midOffsetAtWhole = orderProto.midOffsetAtWhole
+ if orderProto.HasField('midOffsetAtHalf'): order.midOffsetAtHalf = orderProto.midOffsetAtHalf
+ if orderProto.HasField('customerAccount'): order.customerAccount = orderProto.customerAccount
+ if orderProto.HasField('professionalCustomer'): order.professionalCustomer = orderProto.professionalCustomer
+ if orderProto.HasField('bondAccruedInterest'): order.bondAccruedInterest = orderProto.bondAccruedInterest
+ if orderProto.HasField('includeOvernight'): order.includeOvernight = orderProto.includeOvernight
+ if orderProto.HasField('extOperator'): order.extOperator = orderProto.extOperator
+ if orderProto.HasField('manualOrderIndicator'): order.manualOrderIndicator = orderProto.manualOrderIndicator
+ if orderProto.HasField('submitter'): order.submitter = orderProto.submitter
+ if orderProto.HasField('imbalanceOnly'): order.imbalanceOnly = orderProto.imbalanceOnly
+ if orderProto.HasField('autoCancelDate'): order.autoCancelDate = orderProto.autoCancelDate
+ if orderProto.HasField('filledQuantity'): order.filledQuantity = Decimal(orderProto.filledQuantity)
+ if orderProto.HasField('refFuturesConId'): order.refFuturesConId = orderProto.refFuturesConId
+ if orderProto.HasField('shareholder'): order.shareholder = orderProto.shareholder
+ if orderProto.HasField('routeMarketableToBbo'): order.routeMarketableToBbo = orderProto.routeMarketableToBbo
+ if orderProto.HasField('parentPermId'): order.parentPermId = orderProto.parentPermId
+ if orderProto.HasField('postOnly'): order.postOnly = orderProto.postOnly
+ if orderProto.HasField('allowPreOpen'): order.allowPreOpen = orderProto.allowPreOpen
+ if orderProto.HasField('ignoreOpenAuction'): order.ignoreOpenAuction = orderProto.ignoreOpenAuction
+ if orderProto.HasField('deactivate'): order.deactivate = orderProto.deactivate
+ if orderProto.HasField('activeStartTime'): order.activeStartTime = orderProto.activeStartTime
+ if orderProto.HasField('activeStopTime'): order.activeStopTime = orderProto.activeStopTime
+ if orderProto.HasField('seekPriceImprovement'): order.seekPriceImprovement = orderProto.seekPriceImprovement
+ if orderProto.HasField('whatIfType'): order.whatIfType = orderProto.whatIfType
+
+ return order
+
+def decodeConditions(orderProto: OrderProto) -> list[OrderCondition]:
+ orderConditions = []
+ orderConditionsProtoList = []
+ if orderProto.conditions is not None: orderConditionsProtoList = orderProto.conditions
+
+ if orderConditionsProtoList:
+ for orderConditionProto in orderConditionsProtoList:
+ conditionType = orderConditionProto.type if orderConditionProto.HasField('type') else 0
+
+ if OrderCondition.Price == conditionType:
+ condition = createPriceCondition(orderConditionProto)
+ elif OrderCondition.Time == conditionType:
+ condition = createTimeCondition(orderConditionProto)
+ elif OrderCondition.Margin == conditionType:
+ condition = createMarginCondition(orderConditionProto)
+ elif OrderCondition.Execution == conditionType:
+ condition = createExecutionCondition(orderConditionProto)
+ elif OrderCondition.Volume == conditionType:
+ condition = createVolumeCondition(orderConditionProto)
+ elif OrderCondition.PercentChange == conditionType:
+ condition = createPercentChangeCondition(orderConditionProto)
+
+ if condition is not None: orderConditions.append(condition)
+
+ return orderConditions
+
+@staticmethod
+def setConditionFields(orderConditionProto: OrderConditionProto, orderCondition: OrderCondition):
+ if orderConditionProto.HasField('isConjunctionConnection'): orderCondition.isConjunctionConnection = orderConditionProto.isConjunctionConnection
+
+@staticmethod
+def setOperatorConditionFields(orderConditionProto: OrderConditionProto, operatorCondition: OperatorCondition):
+ setConditionFields(orderConditionProto, operatorCondition)
+ if orderConditionProto.HasField('isMore'): operatorCondition.isMore = orderConditionProto.isMore
+
+@staticmethod
+def setContractConditionFields(orderConditionProto: OrderConditionProto, contractCondition: ContractCondition):
+ setOperatorConditionFields(orderConditionProto, contractCondition)
+ if orderConditionProto.HasField('conId'): contractCondition.conId = orderConditionProto.conId
+ if orderConditionProto.HasField('exchange'): contractCondition.exchange = orderConditionProto.exchange
+
+@staticmethod
+def createPriceCondition(orderConditionProto: OrderConditionProto) -> PriceCondition:
+ priceCondition = PriceCondition()
+ setContractConditionFields(orderConditionProto, priceCondition)
+ if orderConditionProto.HasField('price'): priceCondition.price = orderConditionProto.price
+ if orderConditionProto.HasField('triggerMethod'): priceCondition.triggerMethod = orderConditionProto.triggerMethod
+ return priceCondition
+
+@staticmethod
+def createTimeCondition(orderConditionProto: OrderConditionProto) -> TimeCondition:
+ timeCondition = TimeCondition()
+ setOperatorConditionFields(orderConditionProto, timeCondition)
+ if orderConditionProto.HasField('time'): timeCondition.time = orderConditionProto.time
+ return timeCondition
+
+@staticmethod
+def createMarginCondition(orderConditionProto: OrderConditionProto) -> MarginCondition:
+ marginCondition = MarginCondition()
+ setOperatorConditionFields(orderConditionProto, marginCondition)
+ if orderConditionProto.HasField('percent'): marginCondition.percent = orderConditionProto.percent
+ return marginCondition
+
+@staticmethod
+def createExecutionCondition(orderConditionProto: OrderConditionProto) -> ExecutionCondition:
+ executionCondition = ExecutionCondition()
+ setConditionFields(orderConditionProto, executionCondition)
+ if orderConditionProto.HasField('secType'): executionCondition.secType = orderConditionProto.secType
+ if orderConditionProto.HasField('exchange'): executionCondition.exchange = orderConditionProto.exchange
+ if orderConditionProto.HasField('symbol'): executionCondition.symbol = orderConditionProto.symbol
+ return executionCondition
+
+@staticmethod
+def createVolumeCondition(orderConditionProto: OrderConditionProto) -> VolumeCondition:
+ volumeCondition = VolumeCondition()
+ setContractConditionFields(orderConditionProto, volumeCondition)
+ if orderConditionProto.HasField('volume'): volumeCondition.volume = orderConditionProto.volume
+ return volumeCondition
+
+@staticmethod
+def createPercentChangeCondition(orderConditionProto: OrderConditionProto) -> PercentChangeCondition:
+ percentChangeCondition = PercentChangeCondition()
+ setContractConditionFields(orderConditionProto, percentChangeCondition)
+ if orderConditionProto.HasField('changePercent'): percentChangeCondition.changePercent = orderConditionProto.changePercent
+ return percentChangeCondition
+
+@staticmethod
+def decodeSoftDollarTierFromOrder(orderProto: OrderProto) -> SoftDollarTier:
+ softDollarTierProto = None
+ if orderProto.softDollarTier is not None: softDollarTierProto = orderProto.softDollarTier
+ return decodeSoftDollarTier(softDollarTierProto) if softDollarTierProto is not None else None
+
+@staticmethod
+def decodeSoftDollarTier(softDollarTierProto: SoftDollarTierProto) -> SoftDollarTier:
+ name = ""
+ value = ""
+ displayName = ""
+ softDollarTier = None
+ if softDollarTierProto is not None:
+ if softDollarTierProto.HasField('name'): name = softDollarTierProto.name
+ if softDollarTierProto.HasField('value'): value = softDollarTierProto.value
+ if softDollarTierProto.HasField('displayName'): displayName = softDollarTierProto.displayName
+ softDollarTier = SoftDollarTier(name, value, displayName)
+
+ return softDollarTier
+
+@staticmethod
+def decodeTagValueList(protoMap: dict[str, str]) -> list[TagValue]:
+ tagValueList = []
+ if protoMap is not None and protoMap:
+ for tag, value in protoMap.items():
+ tagValue = TagValue()
+ tagValue.tag = tag
+ tagValue.value = value
+ tagValueList.append(tagValue)
+ return tagValueList
+
+@staticmethod
+def decodeOrderState(orderStateProto: OrderStateProto) -> OrderState:
+ orderState = OrderState()
+ if orderStateProto.HasField('status'): orderState.status = orderStateProto.status
+ if orderStateProto.HasField('initMarginBefore'): orderState.initMarginBefore = decimalMaxString(orderStateProto.initMarginBefore)
+ if orderStateProto.HasField('maintMarginBefore'): orderState.maintMarginBefore = decimalMaxString(orderStateProto.maintMarginBefore)
+ if orderStateProto.HasField('equityWithLoanBefore'): orderState.equityWithLoanBefore = decimalMaxString(orderStateProto.equityWithLoanBefore)
+ if orderStateProto.HasField('initMarginChange'): orderState.initMarginChange = decimalMaxString(orderStateProto.initMarginChange)
+ if orderStateProto.HasField('maintMarginChange'): orderState.maintMarginChange = decimalMaxString(orderStateProto.maintMarginChange)
+ if orderStateProto.HasField('equityWithLoanChange'): orderState.equityWithLoanChange = decimalMaxString(orderStateProto.equityWithLoanChange)
+ if orderStateProto.HasField('initMarginAfter'): orderState.initMarginAfter = decimalMaxString(orderStateProto.initMarginAfter)
+ if orderStateProto.HasField('maintMarginAfter'): orderState.maintMarginAfter = decimalMaxString(orderStateProto.maintMarginAfter)
+ if orderStateProto.HasField('equityWithLoanAfter'): orderState.equityWithLoanAfter = decimalMaxString(orderStateProto.equityWithLoanAfter)
+ if orderStateProto.HasField('commissionAndFees'): orderState.commissionAndFees = orderStateProto.commissionAndFees
+ if orderStateProto.HasField('minCommissionAndFees'): orderState.minCommissionAndFees = orderStateProto.minCommissionAndFees
+ if orderStateProto.HasField('maxCommissionAndFees'): orderState.maxCommissionAndFees = orderStateProto.maxCommissionAndFees
+ if orderStateProto.HasField('commissionAndFeesCurrency'): orderState.commissionAndFeesCurrency = orderStateProto.commissionAndFeesCurrency
+ if orderStateProto.HasField('warningText'): orderState.warningText = orderStateProto.warningText
+ if orderStateProto.HasField('marginCurrency'): orderState.marginCurrency = orderStateProto.marginCurrency
+ if orderStateProto.HasField('initMarginBeforeOutsideRTH'): orderState.initMarginBeforeOutsideRTH = orderStateProto.initMarginBeforeOutsideRTH
+ if orderStateProto.HasField('maintMarginBeforeOutsideRTH'): orderState.maintMarginBeforeOutsideRTH = orderStateProto.maintMarginBeforeOutsideRTH
+ if orderStateProto.HasField('equityWithLoanBeforeOutsideRTH'): orderState.equityWithLoanBeforeOutsideRTH = orderStateProto.equityWithLoanBeforeOutsideRTH
+ if orderStateProto.HasField('initMarginChangeOutsideRTH'): orderState.initMarginChangeOutsideRTH = orderStateProto.initMarginChangeOutsideRTH
+ if orderStateProto.HasField('maintMarginChangeOutsideRTH'): orderState.maintMarginChangeOutsideRTH = orderStateProto.maintMarginChangeOutsideRTH
+ if orderStateProto.HasField('equityWithLoanChangeOutsideRTH'): orderState.equityWithLoanChangeOutsideRTH = orderStateProto.equityWithLoanChangeOutsideRTH
+ if orderStateProto.HasField('initMarginAfterOutsideRTH'): orderState.initMarginAfterOutsideRTH = orderStateProto.initMarginAfterOutsideRTH
+ if orderStateProto.HasField('maintMarginAfterOutsideRTH'): orderState.maintMarginAfterOutsideRTH = orderStateProto.maintMarginAfterOutsideRTH
+ if orderStateProto.HasField('equityWithLoanAfterOutsideRTH'): orderState.equityWithLoanAfterOutsideRTH = orderStateProto.equityWithLoanAfterOutsideRTH
+ if orderStateProto.HasField('suggestedSize'): orderState.suggestedSize = Decimal(orderStateProto.suggestedSize)
+ if orderStateProto.HasField('rejectReason'): orderState.rejectReason = orderStateProto.rejectReason
+
+ orderAllocations = decodeOrderAllocations(orderStateProto)
+ if orderAllocations is not None and orderAllocations: orderState.orderAllocations = orderAllocations
+
+ if orderStateProto.HasField('completedTime'): orderState.completedTime = orderStateProto.completedTime
+ if orderStateProto.HasField('completedStatus'): orderState.completedStatus = orderStateProto.completedStatus
+
+ return orderState
+
+@staticmethod
+def decodeOrderAllocations(orderStateProto: OrderStateProto) -> list[OrderAllocation]:
+ orderAllocations = []
+ orderAllocationProtoList = []
+ if orderStateProto.orderAllocations is not None: orderAllocationProtoList = orderStateProto.orderAllocations
+ if orderAllocationProtoList:
+ for orderAllocationProto in orderAllocationProtoList:
+ orderAllocation = OrderAllocation()
+ if orderAllocationProto.HasField('account'): orderAllocation.account = orderAllocationProto.account
+ if orderAllocationProto.HasField('position'): orderAllocation.position = Decimal(orderAllocationProto.position)
+ if orderAllocationProto.HasField('positionDesired'): orderAllocation.positionDesired = Decimal(orderAllocationProto.positionDesired)
+ if orderAllocationProto.HasField('positionAfter'): orderAllocation.positionAfter = Decimal(orderAllocationProto.positionAfter)
+ if orderAllocationProto.HasField('desiredAllocQty'): orderAllocation.desiredAllocQty = Decimal(orderAllocationProto.desiredAllocQty)
+ if orderAllocationProto.HasField('allowedAllocQty'): orderAllocation.allowedAllocQty = Decimal(orderAllocationProto.allowedAllocQty)
+ if orderAllocationProto.HasField('isMonetary'): orderAllocation.isMonetary = orderAllocationProto.isMonetary
+ orderAllocations.append(orderAllocation)
+ return orderAllocations
+
+@staticmethod
+def decodeContractDetails(contractProto: ContractProto, contractDetailsProto: ContractDetailsProto, isBond: bool) -> ContractDetails:
+ contractDetails = ContractDetails()
+ contract = decodeContract(contractProto)
+
+ if contract is not None: contractDetails.contract = contract
+ if contractDetailsProto.HasField('marketName'): contractDetails.marketName = contractDetailsProto.marketName
+ if contractDetailsProto.HasField('minTick'): contractDetails.minTick = float(contractDetailsProto.minTick)
+ if contractDetailsProto.HasField('priceMagnifier'): contractDetails.priceMagnifier = contractDetailsProto.priceMagnifier
+ if contractDetailsProto.HasField('orderTypes'): contractDetails.orderTypes = contractDetailsProto.orderTypes
+ if contractDetailsProto.HasField('validExchanges'): contractDetails.validExchanges = contractDetailsProto.validExchanges
+ if contractDetailsProto.HasField('underConId'): contractDetails.underConId = contractDetailsProto.underConId
+ if contractDetailsProto.HasField('longName'): contractDetails.longName = contractDetailsProto.longName
+ if contractDetailsProto.HasField('contractMonth'): contractDetails.contractMonth = contractDetailsProto.contractMonth
+ if contractDetailsProto.HasField('industry'): contractDetails.industry = contractDetailsProto.industry
+ if contractDetailsProto.HasField('category'): contractDetails.category = contractDetailsProto.category
+ if contractDetailsProto.HasField('subcategory'): contractDetails.subcategory = contractDetailsProto.subcategory
+ if contractDetailsProto.HasField('timeZoneId'): contractDetails.timeZoneId = contractDetailsProto.timeZoneId
+ if contractDetailsProto.HasField('tradingHours'): contractDetails.tradingHours = contractDetailsProto.tradingHours
+ if contractDetailsProto.HasField('liquidHours'): contractDetails.liquidHours = contractDetailsProto.liquidHours
+ if contractDetailsProto.HasField('evRule'): contractDetails.evRule = contractDetailsProto.evRule
+ if contractDetailsProto.HasField('evMultiplier'): contractDetails.evMultiplier = contractDetailsProto.evMultiplier
+
+ contractDetails.secIdList = decodeTagValueList(contractDetailsProto.secIdList)
+
+ if contractDetailsProto.HasField('aggGroup'): contractDetails.aggGroup = contractDetailsProto.aggGroup
+ if contractDetailsProto.HasField('underSymbol'): contractDetails.underSymbol = contractDetailsProto.underSymbol
+ if contractDetailsProto.HasField('underSecType'): contractDetails.underSecType = contractDetailsProto.underSecType
+ if contractDetailsProto.HasField('marketRuleIds'): contractDetails.marketRuleIds = contractDetailsProto.marketRuleIds
+ if contractDetailsProto.HasField('realExpirationDate'): contractDetails.realExpirationDate = contractDetailsProto.realExpirationDate
+ if contractDetailsProto.HasField('stockType'): contractDetails.stockType = contractDetailsProto.stockType
+ if contractDetailsProto.HasField('minSize'): contractDetails.minSize = Decimal(contractDetailsProto.minSize)
+ if contractDetailsProto.HasField('sizeIncrement'): contractDetails.sizeIncrement = Decimal(contractDetailsProto.sizeIncrement)
+ if contractDetailsProto.HasField('suggestedSizeIncrement'): contractDetails.suggestedSizeIncrement = Decimal(contractDetailsProto.suggestedSizeIncrement)
+ if contractDetailsProto.HasField('minAlgoSize'): contractDetails.minAlgoSize = Decimal(contractDetailsProto.minAlgoSize)
+ if contractDetailsProto.HasField('lastPricePrecision'): contractDetails.lastPricePrecision = Decimal(contractDetailsProto.lastPricePrecision)
+ if contractDetailsProto.HasField('lastSizePrecision'): contractDetails.lastSizePrecision = Decimal(contractDetailsProto.lastSizePrecision)
+
+ setLastTradeDate(contract.lastTradeDateOrContractMonth, contractDetails, isBond);
+
+ if contractDetailsProto.HasField('cusip'): contractDetails.cusip = contractDetailsProto.cusip
+ if contractDetailsProto.HasField('ratings'): contractDetails.ratings = contractDetailsProto.ratings
+ if contractDetailsProto.HasField('descAppend'): contractDetails.descAppend = contractDetailsProto.descAppend
+ if contractDetailsProto.HasField('bondType'): contractDetails.bondType = contractDetailsProto.bondType
+ if contractDetailsProto.HasField('coupon'): contractDetails.coupon = contractDetailsProto.coupon
+ if contractDetailsProto.HasField('couponType'): contractDetails.couponType = contractDetailsProto.couponType
+ if contractDetailsProto.HasField('callable'): contractDetails.callable = contractDetailsProto.callable
+ if contractDetailsProto.HasField('puttable'): contractDetails.putable = contractDetailsProto.puttable
+ if contractDetailsProto.HasField('convertible'): contractDetails.convertible = contractDetailsProto.convertible
+ if contractDetailsProto.HasField('issueDate'): contractDetails.issueDate = contractDetailsProto.issueDate
+ if contractDetailsProto.HasField('nextOptionDate'): contractDetails.nextOptionDate = contractDetailsProto.nextOptionDate
+ if contractDetailsProto.HasField('nextOptionType'): contractDetails.nextOptionType = contractDetailsProto.nextOptionType
+ if contractDetailsProto.HasField('nextOptionPartial'): contractDetails.nextOptionPartial = contractDetailsProto.nextOptionPartial
+ if contractDetailsProto.HasField('bondNotes'): contractDetails.notes = contractDetailsProto.bondNotes
+
+ if contractDetailsProto.HasField('fundName'): contractDetails.fundName = contractDetailsProto.fundName
+ if contractDetailsProto.HasField('fundFamily'): contractDetails.fundFamily = contractDetailsProto.fundFamily
+ if contractDetailsProto.HasField('fundType'): contractDetails.fundType = contractDetailsProto.fundType
+ if contractDetailsProto.HasField('fundFrontLoad'): contractDetails.fundFrontLoad = contractDetailsProto.fundFrontLoad
+ if contractDetailsProto.HasField('fundBackLoad'): contractDetails.fundBackLoad = contractDetailsProto.fundBackLoad
+ if contractDetailsProto.HasField('fundBackLoadTimeInterval'): contractDetails.fundBackLoadTimeInterval = contractDetailsProto.fundBackLoadTimeInterval
+ if contractDetailsProto.HasField('fundManagementFee'): contractDetails.fundManagementFee = contractDetailsProto.fundManagementFee
+ if contractDetailsProto.HasField('fundClosed'): contractDetails.fundClosed = contractDetailsProto.fundClosed
+ if contractDetailsProto.HasField('fundClosedForNewInvestors'): contractDetails.fundClosedForNewInvestors = contractDetailsProto.fundClosedForNewInvestors
+ if contractDetailsProto.HasField('fundClosedForNewMoney'): contractDetails.fundClosedForNewMoney = contractDetailsProto.fundClosedForNewMoney
+ if contractDetailsProto.HasField('fundNotifyAmount'): contractDetails.fundNotifyAmount = contractDetailsProto.fundNotifyAmount
+ if contractDetailsProto.HasField('fundMinimumInitialPurchase'): contractDetails.fundMinimumInitialPurchase = contractDetailsProto.fundMinimumInitialPurchase
+ if contractDetailsProto.HasField('fundMinimumSubsequentPurchase'): contractDetails.fundSubsequentMinimumPurchase = contractDetailsProto.fundMinimumSubsequentPurchase
+ if contractDetailsProto.HasField('fundBlueSkyStates'): contractDetails.fundBlueSkyStates = contractDetailsProto.fundBlueSkyStates
+ if contractDetailsProto.HasField('fundBlueSkyTerritories'): contractDetails.fundBlueSkyTerritories = contractDetailsProto.fundBlueSkyTerritories
+
+ if contractDetailsProto.HasField('fundDistributionPolicyIndicator'): contractDetails.fundDistributionPolicyIndicator = getEnumTypeFromString(FundDistributionPolicyIndicator, contractDetailsProto.fundDistributionPolicyIndicator)
+ if contractDetailsProto.HasField('fundAssetType'): contractDetails.fundAssetType = getEnumTypeFromString(FundAssetType, contractDetailsProto.fundAssetType)
+
+ ineligibilityReasonList = decodeIneligibilityReasonList(contractDetailsProto)
+ if ineligibilityReasonList is not None and ineligibilityReasonList: contractDetails.ineligibilityReasonList = ineligibilityReasonList
+
+ if contractDetailsProto.HasField('eventContract1'): contractDetails.eventContract1 = contractDetailsProto.eventContract1
+ if contractDetailsProto.HasField('eventContractDescription1'): contractDetails.eventContractDescription1 = contractDetailsProto.eventContractDescription1
+ if contractDetailsProto.HasField('eventContractDescription2'): contractDetails.eventContractDescription2 = contractDetailsProto.eventContractDescription2
+
+ return contractDetails
+
+@staticmethod
+def decodeIneligibilityReasonList(contractDetailsProto: ContractDetailsProto) -> list[IneligibilityReason]:
+ ineligibilityReasonList = []
+ ineligibilityReasonProtoList = contractDetailsProto.ineligibilityReasonList
+ if ineligibilityReasonProtoList:
+ for ineligibilityReasonProto in ineligibilityReasonProtoList:
+ ineligibilityReason = IneligibilityReason()
+ if ineligibilityReasonProto.HasField('id'): ineligibilityReason.id_ = ineligibilityReasonProto.id
+ if ineligibilityReasonProto.HasField('description'): ineligibilityReason.description = ineligibilityReasonProto.description
+ ineligibilityReasonList.append(ineligibilityReason)
+ return ineligibilityReasonList
+
+@staticmethod
+def setLastTradeDate(lastTradeDateOrContractMonth: str, contract: ContractDetails, isBond: bool):
+ if lastTradeDateOrContractMonth is not None:
+ if "-" in lastTradeDateOrContractMonth:
+ split = lastTradeDateOrContractMonth.split("-")
+ else:
+ split = lastTradeDateOrContractMonth.split()
+
+ if len(split) > 0:
+ if isBond:
+ contract.maturity = split[0]
+ else:
+ contract.contract.lastTradeDateOrContractMonth = split[0]
+
+ if len(split) > 1:
+ contract.lastTradeTime = split[1]
+
+ if isBond and len(split) > 2:
+ contract.timeZoneId = split[2]
+
+@staticmethod
+def decodeHistoricalTick(historicalTickProto: HistoricalTickProto) -> HistoricalTick:
+ historicalTick = HistoricalTick()
+ if historicalTickProto.HasField('time'): historicalTick.time = historicalTickProto.time
+ if historicalTickProto.HasField('price'): historicalTick.price = historicalTickProto.price
+ if historicalTickProto.HasField('size'): historicalTick.size = Decimal(historicalTickProto.size)
+ return historicalTick
+
+@staticmethod
+def decodeHistoricalTickBidAsk(historicalTickBidAskProto: HistoricalTickBidAskProto) -> HistoricalTickBidAsk:
+ historicalTickBidAsk = HistoricalTickBidAsk()
+ if historicalTickBidAskProto.HasField('time'): historicalTickBidAsk.time = historicalTickBidAskProto.time
+
+ tickAttribBidAsk = TickAttribBidAsk()
+ if historicalTickBidAskProto.HasField('tickAttribBidAsk'):
+ tickAttribBidAskProto = historicalTickBidAskProto.tickAttribBidAsk
+ if tickAttribBidAskProto.HasField('bidPastLow'): tickAttribBidAsk.bidPastLow = tickAttribBidAskProto.bidPastLow
+ if tickAttribBidAskProto.HasField('askPastHigh'): tickAttribBidAsk.askPastHigh = tickAttribBidAskProto.askPastHigh
+ historicalTickBidAsk.tickAttribBidAsk = tickAttribBidAsk
+
+ if historicalTickBidAskProto.HasField('priceBid'): historicalTickBidAsk.priceBid = historicalTickBidAskProto.priceBid
+ if historicalTickBidAskProto.HasField('priceAsk'): historicalTickBidAsk.priceAsk = historicalTickBidAskProto.priceAsk
+ if historicalTickBidAskProto.HasField('sizeBid'): historicalTickBidAsk.sizeBid = Decimal(historicalTickBidAskProto.sizeBid)
+ if historicalTickBidAskProto.HasField('sizeAsk'): historicalTickBidAsk.sizeAsk = Decimal(historicalTickBidAskProto.sizeAsk)
+ return historicalTickBidAsk
+
+@staticmethod
+def decodeHistoricalTickLast(historicalTickLastProto: HistoricalTickLastProto) -> HistoricalTickLast:
+ historicalTickLast = HistoricalTickLast()
+ if historicalTickLastProto.HasField('time'): historicalTickLast.time = historicalTickLastProto.time
+
+ tickAttribLast = TickAttribLast()
+ if historicalTickLastProto.HasField('tickAttribLast'):
+ tickAttribLastProto = historicalTickLastProto.tickAttribLast
+ if tickAttribLastProto.HasField('pastLimit'): tickAttribLast.pastLimit = tickAttribLastProto.pastLimit
+ if tickAttribLastProto.HasField('unreported'): tickAttribLast.unreported = tickAttribLastProto.unreported
+ historicalTickLast.tickAttribLast = tickAttribLast
+
+ if historicalTickLastProto.HasField('price'): historicalTickLast.price = historicalTickLastProto.price
+ if historicalTickLastProto.HasField('size'): historicalTickLast.size = Decimal(historicalTickLastProto.size)
+ if historicalTickLastProto.HasField('exchange'): historicalTickLast.exchange = historicalTickLastProto.exchange
+ if historicalTickLastProto.HasField('specialConditions'): historicalTickLast.specialConditions = historicalTickLastProto.specialConditions
+ return historicalTickLast
+
+@staticmethod
+def decodeHistogramDataEntry(histogramDataEntryProto: HistogramDataEntryProto) -> HistogramData:
+ histogramData = HistogramData()
+ if histogramDataEntryProto.HasField('price'): histogramData.price = histogramDataEntryProto.price
+ if histogramDataEntryProto.HasField('size'): histogramData.size = Decimal(histogramDataEntryProto.size)
+ return histogramData
+
+@staticmethod
+def decodeHistoricalDataBar(historicalDataBarProto: HistoricalDataBarProto) -> BarData:
+ bar = BarData()
+ if historicalDataBarProto.HasField('date'): bar.date = historicalDataBarProto.date
+ if historicalDataBarProto.HasField('open'): bar.open = historicalDataBarProto.open
+ if historicalDataBarProto.HasField('high'): bar.high = historicalDataBarProto.high
+ if historicalDataBarProto.HasField('low'): bar.low = historicalDataBarProto.low
+ if historicalDataBarProto.HasField('close'): bar.close = historicalDataBarProto.close
+ if historicalDataBarProto.HasField('volume'): bar.volume = Decimal(historicalDataBarProto.volume)
+ if historicalDataBarProto.HasField('WAP'): bar.wap = Decimal(historicalDataBarProto.WAP)
+ if historicalDataBarProto.HasField('barCount'): bar.barCount = historicalDataBarProto.barCount
+ return bar
+
+@staticmethod
+def decodeFamilyCode(familyCodeProto: FamilyCodeProto) -> FamilyCode:
+ familyCode = FamilyCode()
+ if familyCodeProto and familyCodeProto.HasField('accountId'): familyCode.accountID = familyCodeProto.accountId
+ if familyCodeProto and familyCodeProto.HasField('familyCode'): familyCode.familyCodeStr = familyCodeProto.familyCode
+ return familyCode
+
+@staticmethod
+def decodeSmartComponents(smartComponentsProto: SmartComponentsProto) -> SmartComponentMap:
+ smartComponentMap = {}
+ if smartComponentsProto and smartComponentsProto.smartComponents:
+ for smartComponentProto in smartComponentsProto.smartComponents:
+ bitNumber = smartComponentProto.bitNumber if smartComponentProto.HasField('bitNumber') else 0
+ exchange = smartComponentProto.exchange if smartComponentProto.HasField('exchange') else ""
+ exchangeLetter = smartComponentProto.exchangeLetter if smartComponentProto.HasField('exchangeLetter') else " "
+ smartComponentMap[bitNumber] = (exchange, exchangeLetter)
+ return smartComponentMap
+
+@staticmethod
+def decodePriceIncrement(priceIncrementProto: PriceIncrementProto) -> PriceIncrement:
+ priceIncrement = PriceIncrement()
+ if priceIncrementProto and priceIncrementProto.HasField('lowEdge'): priceIncrement.lowEdge = priceIncrementProto.lowEdge
+ if priceIncrementProto and priceIncrementProto.HasField('increment'): priceIncrement.increment = priceIncrementProto.increment
+ return priceIncrement
+
+@staticmethod
+def decodeDepthMarketDataDescription(depthMarketDataDescriptionProto: DepthMarketDataDescriptionProto) -> DepthMktDataDescription:
+ description = DepthMktDataDescription()
+ if depthMarketDataDescriptionProto.HasField('exchange'): description.exchange = depthMarketDataDescriptionProto.exchange
+ if depthMarketDataDescriptionProto.HasField('secType'): description.secType = depthMarketDataDescriptionProto.secType
+ if depthMarketDataDescriptionProto.HasField('listingExch'): description.listingExch = depthMarketDataDescriptionProto.listingExch
+ if depthMarketDataDescriptionProto.HasField('serviceDataType'): description.serviceDataType = depthMarketDataDescriptionProto.serviceDataType
+ if depthMarketDataDescriptionProto.HasField('aggGroup'): description.aggGroup = depthMarketDataDescriptionProto.aggGroup
+ return description
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/enum_implem.py b/packages/ibkr/ref/source/pythonclient/ibapi/enum_implem.py
new file mode 100644
index 00000000..d53dfdb7
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/enum_implem.py
@@ -0,0 +1,20 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+"""
+ Simple enum implementation
+"""
+
+
+class Enum:
+ def __init__(self, *args):
+ self.idx2name = {}
+ for idx, name in enumerate(args):
+ setattr(self, name, idx)
+ self.idx2name[idx] = name
+
+ def toStr(self, idx):
+ return self.idx2name.get(idx, "NOTFOUND")
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/errors.py b/packages/ibkr/ref/source/pythonclient/ibapi/errors.py
new file mode 100644
index 00000000..9633f783
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/errors.py
@@ -0,0 +1,119 @@
+"""
+Copyright (C) 2023 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+
+This is the interface that will need to be overloaded by the customer so
+that his/her code can receive info from the TWS/IBGW.
+"""
+
+
+class CodeMsgPair:
+ def __init__(self, code, msg):
+ self.errorCode = code
+ self.errorMsg = msg
+
+ def code(self):
+ return self.errorCode
+
+ def msg(self):
+ return self.errorMsg
+
+
+ALREADY_CONNECTED = CodeMsgPair(501, "Already connected.")
+CONNECT_FAIL = CodeMsgPair(
+ 502,
+ """Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket Clients\"
+is enabled and connection port is the same as \"Socket Port\" on the
+TWS \"Edit->Global Configuration...->API->Settings\" menu. Live Trading ports:
+TWS: 7496; IB Gateway: 4001. Simulated Trading ports: TWS: 7497; IB Gateway: 4002.
+Verify that the maximum API connection threshold (default 32) is not exceeded.""",
+)
+UPDATE_TWS = CodeMsgPair(503, "The TWS is out of date and must be upgraded.")
+NOT_CONNECTED = CodeMsgPair(504, "Not connected")
+UNKNOWN_ID = CodeMsgPair(505, "Fatal Error: Unknown message id.")
+# UNSUPPORTED_VERSION = CodeMsgPair(506, "Unsupported version") #not used
+BAD_LENGTH = CodeMsgPair(507, "Bad message length")
+BAD_MESSAGE = CodeMsgPair(508, "Bad message")
+# SOCKET_EXCEPTION = CodeMsgPair(509, "Exception caught while reading socket - ") #not used
+FAIL_SEND_REQMKT = CodeMsgPair(510, "Request Market Data Sending Error - ")
+FAIL_SEND_CANMKT = CodeMsgPair(511, "Cancel Market Data Sending Error - ")
+FAIL_SEND_ORDER = CodeMsgPair(512, "Order Sending Error - ")
+FAIL_SEND_ACCT = CodeMsgPair(513, "Account Update Request Sending Error - ")
+FAIL_SEND_EXEC = CodeMsgPair(514, "Request For Executions Sending Error - ")
+FAIL_SEND_CORDER = CodeMsgPair(515, "Cancel Order Sending Error - ")
+FAIL_SEND_OORDER = CodeMsgPair(516, "Request Open Order Sending Error - ")
+FAIL_SEND_REQCONTRACT = CodeMsgPair(518, "Request Contract Data Sending Error - ")
+FAIL_SEND_REQMKTDEPTH = CodeMsgPair(519, "Request Market Depth Sending Error - ")
+FAIL_CREATE_SOCK = CodeMsgPair(520, "Failed to create socket")
+FAIL_SEND_SERVER_LOG_LEVEL = CodeMsgPair(521, "Set Server Log Level Sending Error - ")
+FAIL_SEND_FA_REQUEST = CodeMsgPair(522, "FA Information Request Sending Error - ")
+FAIL_SEND_FA_REPLACE = CodeMsgPair(523, "FA Information Replace Sending Error - ")
+FAIL_SEND_REQSCANNER = CodeMsgPair(524, "Request Scanner Subscription Sending Error - ")
+FAIL_SEND_CANSCANNER = CodeMsgPair(525, "Cancel Scanner Subscription Sending Error - ")
+FAIL_SEND_REQSCANNERPARAMETERS = CodeMsgPair(526, "Request Scanner Parameter Sending Error - ")
+FAIL_SEND_REQHISTDATA = CodeMsgPair(527, "Request Historical Data Sending Error - ")
+FAIL_SEND_CANHISTDATA = CodeMsgPair(528, "Request Historical Data Sending Error - ")
+FAIL_SEND_REQRTBARS = CodeMsgPair(529, "Request Real-time Bar Data Sending Error - ")
+FAIL_SEND_CANRTBARS = CodeMsgPair(530, "Cancel Real-time Bar Data Sending Error - ")
+FAIL_SEND_REQCURRTIME = CodeMsgPair(531, "Request Current Time Sending Error - ")
+FAIL_SEND_REQFUNDDATA = CodeMsgPair(532, "Request Fundamental Data Sending Error - ")
+FAIL_SEND_CANFUNDDATA = CodeMsgPair(533, "Cancel Fundamental Data Sending Error - ")
+FAIL_SEND_REQCALCIMPLIEDVOLAT = CodeMsgPair(534, "Request Calculate Implied Volatility Sending Error - ")
+FAIL_SEND_REQCALCOPTIONPRICE = CodeMsgPair(535, "Request Calculate Option Price Sending Error - ")
+FAIL_SEND_CANCALCIMPLIEDVOLAT = CodeMsgPair(536, "Cancel Calculate Implied Volatility Sending Error - ")
+FAIL_SEND_CANCALCOPTIONPRICE = CodeMsgPair(537, "Cancel Calculate Option Price Sending Error - ")
+FAIL_SEND_REQGLOBALCANCEL = CodeMsgPair(538, "Request Global Cancel Sending Error - ")
+FAIL_SEND_REQMARKETDATATYPE = CodeMsgPair(539, "Request Market Data Type Sending Error - ")
+FAIL_SEND_REQPOSITIONS = CodeMsgPair(540, "Request Positions Sending Error - ")
+FAIL_SEND_CANPOSITIONS = CodeMsgPair(541, "Cancel Positions Sending Error - ")
+FAIL_SEND_REQACCOUNTDATA = CodeMsgPair(542, "Request Account Data Sending Error - ")
+FAIL_SEND_CANACCOUNTDATA = CodeMsgPair(543, "Cancel Account Data Sending Error - ")
+FAIL_SEND_VERIFYREQUEST = CodeMsgPair(544, "Verify Request Sending Error - ")
+FAIL_SEND_VERIFYMESSAGE = CodeMsgPair(545, "Verify Message Sending Error - ")
+FAIL_SEND_QUERYDISPLAYGROUPS = CodeMsgPair(546, "Query Display Groups Sending Error - ")
+FAIL_SEND_SUBSCRIBETOGROUPEVENTS = CodeMsgPair(547, "Subscribe To Group Events Sending Error - ")
+FAIL_SEND_UPDATEDISPLAYGROUP = CodeMsgPair(548, "Update Display Group Sending Error - ")
+FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS = CodeMsgPair(549, "Unsubscribe From Group Events Sending Error - ")
+FAIL_SEND_STARTAPI = CodeMsgPair(550, "Start API Sending Error - ")
+FAIL_SEND_VERIFYANDAUTHREQUEST = CodeMsgPair(551, "Verify And Auth Request Sending Error - ")
+FAIL_SEND_VERIFYANDAUTHMESSAGE = CodeMsgPair(552, "Verify And Auth Message Sending Error - ")
+FAIL_SEND_REQPOSITIONSMULTI = CodeMsgPair(553, "Request Positions Multi Sending Error - ")
+FAIL_SEND_CANPOSITIONSMULTI = CodeMsgPair(554, "Cancel Positions Multi Sending Error - ")
+FAIL_SEND_REQACCOUNTUPDATESMULTI = CodeMsgPair(555, "Request Account Updates Multi Sending Error - ")
+FAIL_SEND_CANACCOUNTUPDATESMULTI = CodeMsgPair(556, "Cancel Account Updates Multi Sending Error - ")
+FAIL_SEND_REQSECDEFOPTPARAMS = CodeMsgPair(557, "Request Security Definition Option Params Sending Error - ")
+FAIL_SEND_REQSOFTDOLLARTIERS = CodeMsgPair(558, "Request Soft Dollar Tiers Sending Error - ")
+FAIL_SEND_REQFAMILYCODES = CodeMsgPair(559, "Request Family Codes Sending Error - ")
+FAIL_SEND_REQMATCHINGSYMBOLS = CodeMsgPair(560, "Request Matching Symbols Sending Error - ")
+FAIL_SEND_REQMKTDEPTHEXCHANGES = CodeMsgPair(561, "Request Market Depth Exchanges Sending Error - ")
+FAIL_SEND_REQSMARTCOMPONENTS = CodeMsgPair(562, "Request Smart Components Sending Error - ")
+FAIL_SEND_REQNEWSPROVIDERS = CodeMsgPair(563, "Request News Providers Sending Error - ")
+FAIL_SEND_REQNEWSARTICLE = CodeMsgPair(564, "Request News Article Sending Error - ")
+FAIL_SEND_REQHISTORICALNEWS = CodeMsgPair(565, "Request Historical News Sending Error - ")
+FAIL_SEND_REQHEADTIMESTAMP = CodeMsgPair(566, "Request Head Time Stamp Sending Error - ")
+FAIL_SEND_REQHISTOGRAMDATA = CodeMsgPair(567, "Request Histogram Data Sending Error - ")
+FAIL_SEND_CANCELHISTOGRAMDATA = CodeMsgPair(568, "Cancel Request Histogram Data Sending Error - ")
+FAIL_SEND_CANCELHEADTIMESTAMP = CodeMsgPair(569, "Cancel Head Time Stamp Sending Error - ")
+FAIL_SEND_REQMARKETRULE = CodeMsgPair(570, "Request Market Rule Sending Error - ")
+FAIL_SEND_REQPNL = CodeMsgPair(571, "Request PnL Sending Error - ")
+FAIL_SEND_CANCELPNL = CodeMsgPair(572, "Cancel PnL Sending Error - ")
+FAIL_SEND_REQPNLSINGLE = CodeMsgPair(573, "Request PnL Single Error - ")
+FAIL_SEND_CANCELPNLSINGLE = CodeMsgPair(574, "Cancel PnL Single Sending Error - ")
+FAIL_SEND_REQHISTORICALTICKS = CodeMsgPair(575, "Request Historical Ticks Error - ")
+FAIL_SEND_REQTICKBYTICKDATA = CodeMsgPair(576, "Request Tick-By-Tick Data Sending Error - ")
+FAIL_SEND_CANCELTICKBYTICKDATA = CodeMsgPair(577, "Cancel Tick-By-Tick Data Sending Error - ")
+FAIL_SEND_REQCOMPLETEDORDERS = CodeMsgPair(578, "Request Completed Orders Sending Error - ")
+INVALID_SYMBOL = CodeMsgPair(579, "Invalid symbol in string - ")
+FAIL_SEND_REQ_WSH_META_DATA = CodeMsgPair(580, "Request WSH Meta Data Sending Error - ")
+FAIL_SEND_CAN_WSH_META_DATA = CodeMsgPair(581, "Cancel WSH Meta Data Sending Error - ")
+FAIL_SEND_REQ_WSH_EVENT_DATA = CodeMsgPair(582, "Request WSH Event Data Sending Error - ")
+FAIL_SEND_CAN_WSH_EVENT_DATA = CodeMsgPair(583, "Cancel WSH Event Data Sending Error - ")
+FAIL_SEND_REQ_USER_INFO = CodeMsgPair(584, "Request User Info Sending Error - ")
+FA_PROFILE_NOT_SUPPORTED = CodeMsgPair(585, "FA Profile is not supported anymore, use FA Group instead - ")
+FAIL_SEND_REQCURRTIMEINMILLIS = CodeMsgPair(587, "Request Current Time In Millis Sending Error - ")
+ERROR_ENCODING_PROTOBUF = CodeMsgPair(588, "Error encoding protobuf - ")
+FAIL_SEND_CANMKTDEPTH = CodeMsgPair(589, "Cancel Market Depth Sending Error - ")
+FAIL_SEND_CANCEL_CONTRACT_DATA = CodeMsgPair(590, "Cancel Contract Data Sending Error - ")
+FAIL_SEND_CANCEL_HISTORICAL_TICKS = CodeMsgPair(591, "Cancel Historical Ticks Sending Error - ")
+FAIL_SEND_REQCONFIG = CodeMsgPair(592, "Request Config Sending Error - ")
+FAIL_SEND_UPDATECONFIG = CodeMsgPair(593, "Update Config Request Sending Error - ")
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/execution.py b/packages/ibkr/ref/source/pythonclient/ibapi/execution.py
new file mode 100644
index 00000000..37ec887f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/execution.py
@@ -0,0 +1,95 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+from ibapi.object_implem import Object
+from ibapi.const import UNSET_DECIMAL
+from ibapi.const import UNSET_INTEGER
+from ibapi.utils import decimalMaxString
+from ibapi.utils import intMaxString
+from ibapi.utils import floatMaxString
+from ibapi.utils import longMaxString
+from ibapi.utils import getEnumTypeName
+from enum import Enum
+
+class Execution(Object):
+ def __init__(self):
+ self.execId = ""
+ self.time = ""
+ self.acctNumber = ""
+ self.exchange = ""
+ self.side = ""
+ self.shares = UNSET_DECIMAL
+ self.price = 0.0
+ self.permId = 0
+ self.clientId = 0
+ self.orderId = 0
+ self.liquidation = 0
+ self.cumQty = UNSET_DECIMAL
+ self.avgPrice = 0.0
+ self.orderRef = ""
+ self.evRule = ""
+ self.evMultiplier = 0.0
+ self.modelCode = ""
+ self.lastLiquidity = 0
+ self.pendingPriceRevision = False
+ self.submitter = ""
+ self.optExerciseOrLapseType = OptionExerciseType.NoneItem
+
+ def __str__(self):
+ return (
+ "ExecId: %s, Time: %s, Account: %s, Exchange: %s, Side: %s, Shares: %s, Price: %s, PermId: %s, "
+ "ClientId: %s, OrderId: %s, Liquidation: %s, CumQty: %s, AvgPrice: %s, OrderRef: %s, EvRule: %s, "
+ "EvMultiplier: %s, ModelCode: %s, LastLiquidity: %s, PendingPriceRevision: %s, Submitter: %s, OptExerciseOrLapseType: %s"
+ % (
+ self.execId,
+ self.time,
+ self.acctNumber,
+ self.exchange,
+ self.side,
+ decimalMaxString(self.shares),
+ floatMaxString(self.price),
+ longMaxString(self.permId),
+ intMaxString(self.clientId),
+ intMaxString(self.orderId),
+ intMaxString(self.liquidation),
+ decimalMaxString(self.cumQty),
+ floatMaxString(self.avgPrice),
+ self.orderRef,
+ self.evRule,
+ floatMaxString(self.evMultiplier),
+ self.modelCode,
+ intMaxString(self.lastLiquidity),
+ self.pendingPriceRevision,
+ self.submitter,
+ getEnumTypeName(OptionExerciseType, self.optExerciseOrLapseType),
+ )
+ )
+
+
+class ExecutionFilter(Object):
+ # Filter fields
+ def __init__(self):
+ self.clientId = 0
+ self.acctCode = ""
+ self.time = ""
+ self.symbol = ""
+ self.secType = ""
+ self.exchange = ""
+ self.side = ""
+ self.lastNDays = UNSET_INTEGER
+ self.specificDates = None
+
+class OptionExerciseType(Enum):
+ NoneItem = (-1, "None")
+ Exercise = (1, "Exercise")
+ Lapse = (2, "Lapse")
+ DoNothing = (3, "DoNothing")
+ Assigned = (100, "Assigned ")
+ AutoexerciseClearing = (101, "AutoexerciseClearing")
+ Expired = (102, "Expired")
+ Netting = (103, "Netting")
+ AutoexerciseTrading = (200, "AutoexerciseTrading")
+
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/ibapi.pyproj b/packages/ibkr/ref/source/pythonclient/ibapi/ibapi.pyproj
new file mode 100644
index 00000000..7cb1a10f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/ibapi.pyproj
@@ -0,0 +1,57 @@
+
+
+
+ Debug
+ 2.0
+ {aa7df1c2-6d30-4556-b6d5-a188f972bbdd}
+
+ account_summary_tags.py
+ protobuf
+ .
+ .
+ {888888a0-9f3d-457c-b088-3a5042f75d52}
+ Standard Python launcher
+
+
+
+
+
+ 10.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/ineligibility_reason.py b/packages/ibkr/ref/source/pythonclient/ibapi/ineligibility_reason.py
new file mode 100644
index 00000000..cf057496
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/ineligibility_reason.py
@@ -0,0 +1,18 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+"""
+Simple class for ineligibility reason
+"""
+
+from ibapi.object_implem import Object
+
+class IneligibilityReason(Object):
+ def __init__(self, id_: str = None, description: str = None):
+ self.id_ = str(id_)
+ self.description = str(description)
+
+ def __str__(self):
+ return f"[id: {self.id_}, description: {self.description}];"
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/message.py b/packages/ibkr/ref/source/pythonclient/ibapi/message.py
new file mode 100644
index 00000000..caee3b4f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/message.py
@@ -0,0 +1,192 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+"""
+High level IB message info.
+"""
+
+# field types
+INT = 1
+STR = 2
+FLT = 3
+
+
+# incoming msg id's
+class IN:
+ TICK_PRICE = 1
+ TICK_SIZE = 2
+ ORDER_STATUS = 3
+ ERR_MSG = 4
+ OPEN_ORDER = 5
+ ACCT_VALUE = 6
+ PORTFOLIO_VALUE = 7
+ ACCT_UPDATE_TIME = 8
+ NEXT_VALID_ID = 9
+ CONTRACT_DATA = 10
+ EXECUTION_DATA = 11
+ MARKET_DEPTH = 12
+ MARKET_DEPTH_L2 = 13
+ NEWS_BULLETINS = 14
+ MANAGED_ACCTS = 15
+ RECEIVE_FA = 16
+ HISTORICAL_DATA = 17
+ BOND_CONTRACT_DATA = 18
+ SCANNER_PARAMETERS = 19
+ SCANNER_DATA = 20
+ TICK_OPTION_COMPUTATION = 21
+ TICK_GENERIC = 45
+ TICK_STRING = 46
+ TICK_EFP = 47
+ CURRENT_TIME = 49
+ REAL_TIME_BARS = 50
+ FUNDAMENTAL_DATA = 51
+ CONTRACT_DATA_END = 52
+ OPEN_ORDER_END = 53
+ ACCT_DOWNLOAD_END = 54
+ EXECUTION_DATA_END = 55
+ DELTA_NEUTRAL_VALIDATION = 56
+ TICK_SNAPSHOT_END = 57
+ MARKET_DATA_TYPE = 58
+ COMMISSION_AND_FEES_REPORT = 59
+ POSITION_DATA = 61
+ POSITION_END = 62
+ ACCOUNT_SUMMARY = 63
+ ACCOUNT_SUMMARY_END = 64
+ VERIFY_MESSAGE_API = 65
+ VERIFY_COMPLETED = 66
+ DISPLAY_GROUP_LIST = 67
+ DISPLAY_GROUP_UPDATED = 68
+ VERIFY_AND_AUTH_MESSAGE_API = 69
+ VERIFY_AND_AUTH_COMPLETED = 70
+ POSITION_MULTI = 71
+ POSITION_MULTI_END = 72
+ ACCOUNT_UPDATE_MULTI = 73
+ ACCOUNT_UPDATE_MULTI_END = 74
+ SECURITY_DEFINITION_OPTION_PARAMETER = 75
+ SECURITY_DEFINITION_OPTION_PARAMETER_END = 76
+ SOFT_DOLLAR_TIERS = 77
+ FAMILY_CODES = 78
+ SYMBOL_SAMPLES = 79
+ MKT_DEPTH_EXCHANGES = 80
+ TICK_REQ_PARAMS = 81
+ SMART_COMPONENTS = 82
+ NEWS_ARTICLE = 83
+ TICK_NEWS = 84
+ NEWS_PROVIDERS = 85
+ HISTORICAL_NEWS = 86
+ HISTORICAL_NEWS_END = 87
+ HEAD_TIMESTAMP = 88
+ HISTOGRAM_DATA = 89
+ HISTORICAL_DATA_UPDATE = 90
+ REROUTE_MKT_DATA_REQ = 91
+ REROUTE_MKT_DEPTH_REQ = 92
+ MARKET_RULE = 93
+ PNL = 94
+ PNL_SINGLE = 95
+ HISTORICAL_TICKS = 96
+ HISTORICAL_TICKS_BID_ASK = 97
+ HISTORICAL_TICKS_LAST = 98
+ TICK_BY_TICK = 99
+ ORDER_BOUND = 100
+ COMPLETED_ORDER = 101
+ COMPLETED_ORDERS_END = 102
+ REPLACE_FA_END = 103
+ WSH_META_DATA = 104
+ WSH_EVENT_DATA = 105
+ HISTORICAL_SCHEDULE = 106
+ USER_INFO = 107
+ HISTORICAL_DATA_END = 108
+ CURRENT_TIME_IN_MILLIS = 109
+ CONFIG_RESPONSE = 110
+ UPDATE_CONFIG_RESPONSE = 111
+
+
+# outgoing msg id's
+class OUT:
+ REQ_MKT_DATA = 1
+ CANCEL_MKT_DATA = 2
+ PLACE_ORDER = 3
+ CANCEL_ORDER = 4
+ REQ_OPEN_ORDERS = 5
+ REQ_ACCT_DATA = 6
+ REQ_EXECUTIONS = 7
+ REQ_IDS = 8
+ REQ_CONTRACT_DATA = 9
+ REQ_MKT_DEPTH = 10
+ CANCEL_MKT_DEPTH = 11
+ REQ_NEWS_BULLETINS = 12
+ CANCEL_NEWS_BULLETINS = 13
+ SET_SERVER_LOGLEVEL = 14
+ REQ_AUTO_OPEN_ORDERS = 15
+ REQ_ALL_OPEN_ORDERS = 16
+ REQ_MANAGED_ACCTS = 17
+ REQ_FA = 18
+ REPLACE_FA = 19
+ REQ_HISTORICAL_DATA = 20
+ EXERCISE_OPTIONS = 21
+ REQ_SCANNER_SUBSCRIPTION = 22
+ CANCEL_SCANNER_SUBSCRIPTION = 23
+ REQ_SCANNER_PARAMETERS = 24
+ CANCEL_HISTORICAL_DATA = 25
+ REQ_CURRENT_TIME = 49
+ REQ_REAL_TIME_BARS = 50
+ CANCEL_REAL_TIME_BARS = 51
+ REQ_FUNDAMENTAL_DATA = 52
+ CANCEL_FUNDAMENTAL_DATA = 53
+ REQ_CALC_IMPLIED_VOLAT = 54
+ REQ_CALC_OPTION_PRICE = 55
+ CANCEL_CALC_IMPLIED_VOLAT = 56
+ CANCEL_CALC_OPTION_PRICE = 57
+ REQ_GLOBAL_CANCEL = 58
+ REQ_MARKET_DATA_TYPE = 59
+ REQ_POSITIONS = 61
+ REQ_ACCOUNT_SUMMARY = 62
+ CANCEL_ACCOUNT_SUMMARY = 63
+ CANCEL_POSITIONS = 64
+ VERIFY_REQUEST = 65
+ VERIFY_MESSAGE = 66
+ QUERY_DISPLAY_GROUPS = 67
+ SUBSCRIBE_TO_GROUP_EVENTS = 68
+ UPDATE_DISPLAY_GROUP = 69
+ UNSUBSCRIBE_FROM_GROUP_EVENTS = 70
+ START_API = 71
+ VERIFY_AND_AUTH_REQUEST = 72
+ VERIFY_AND_AUTH_MESSAGE = 73
+ REQ_POSITIONS_MULTI = 74
+ CANCEL_POSITIONS_MULTI = 75
+ REQ_ACCOUNT_UPDATES_MULTI = 76
+ CANCEL_ACCOUNT_UPDATES_MULTI = 77
+ REQ_SEC_DEF_OPT_PARAMS = 78
+ REQ_SOFT_DOLLAR_TIERS = 79
+ REQ_FAMILY_CODES = 80
+ REQ_MATCHING_SYMBOLS = 81
+ REQ_MKT_DEPTH_EXCHANGES = 82
+ REQ_SMART_COMPONENTS = 83
+ REQ_NEWS_ARTICLE = 84
+ REQ_NEWS_PROVIDERS = 85
+ REQ_HISTORICAL_NEWS = 86
+ REQ_HEAD_TIMESTAMP = 87
+ REQ_HISTOGRAM_DATA = 88
+ CANCEL_HISTOGRAM_DATA = 89
+ CANCEL_HEAD_TIMESTAMP = 90
+ REQ_MARKET_RULE = 91
+ REQ_PNL = 92
+ CANCEL_PNL = 93
+ REQ_PNL_SINGLE = 94
+ CANCEL_PNL_SINGLE = 95
+ REQ_HISTORICAL_TICKS = 96
+ REQ_TICK_BY_TICK_DATA = 97
+ CANCEL_TICK_BY_TICK_DATA = 98
+ REQ_COMPLETED_ORDERS = 99
+ REQ_WSH_META_DATA = 100
+ CANCEL_WSH_META_DATA = 101
+ REQ_WSH_EVENT_DATA = 102
+ CANCEL_WSH_EVENT_DATA = 103
+ REQ_USER_INFO = 104
+ REQ_CURRENT_TIME_IN_MILLIS = 105
+ CANCEL_CONTRACT_DATA = 106
+ CANCEL_HISTORICAL_TICKS = 107
+ REQ_CONFIG = 108
+ UPDATE_CONFIG = 109
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/news.py b/packages/ibkr/ref/source/pythonclient/ibapi/news.py
new file mode 100644
index 00000000..0552cac0
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/news.py
@@ -0,0 +1,13 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+# TWS New Bulletins constants
+NEWS_MSG = 1 # standard IB news bulleting message
+EXCHANGE_AVAIL_MSG = (
+ 2 # control message specifying that an exchange is available for trading
+)
+EXCHANGE_UNAVAIL_MSG = (
+ 3 # control message specifying that an exchange is unavailable for trading
+)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/object_implem.py b/packages/ibkr/ref/source/pythonclient/ibapi/object_implem.py
new file mode 100644
index 00000000..0dcb3a2f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/object_implem.py
@@ -0,0 +1,12 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+class Object(object):
+ def __str__(self):
+ return "Object"
+
+ def __repr__(self):
+ return str(id(self)) + ": " + self.__str__()
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/order.py b/packages/ibkr/ref/source/pythonclient/ibapi/order.py
new file mode 100644
index 00000000..3a7f5c63
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/order.py
@@ -0,0 +1,275 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.const import UNSET_INTEGER, UNSET_DOUBLE, UNSET_DECIMAL, DOUBLE_INFINITY
+from ibapi.object_implem import Object
+from ibapi.softdollartier import SoftDollarTier
+from ibapi.utils import decimalMaxString
+from ibapi.utils import intMaxString
+from ibapi.utils import floatMaxString
+from ibapi.utils import longMaxString
+
+# enum Origin
+(CUSTOMER, FIRM, UNKNOWN) = range(3)
+
+# enum AuctionStrategy
+(AUCTION_UNSET, AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT) = range(4)
+
+COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID = DOUBLE_INFINITY
+
+
+class OrderComboLeg(Object):
+ def __init__(self):
+ self.price = UNSET_DOUBLE # type: float
+
+ def __str__(self):
+ return f"{floatMaxString(self.price)}"
+
+
+class Order(Object):
+ def __init__(self):
+ self.softDollarTier = SoftDollarTier("", "", "")
+ # order identifier
+ self.orderId = 0
+ self.clientId = 0
+ self.permId = 0
+
+ # main order fields
+ self.action = ""
+ self.totalQuantity = UNSET_DECIMAL
+ self.orderType = ""
+ self.lmtPrice = UNSET_DOUBLE
+ self.auxPrice = UNSET_DOUBLE
+
+ # extended order fields
+ self.tif = "" # "Time in Force" - DAY, GTC, etc.
+ self.activeStartTime = "" # for GTC orders
+ self.activeStopTime = "" # for GTC orders
+ self.ocaGroup = "" # one cancels all group name
+ self.ocaType = (
+ 0 # 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK
+ )
+ self.orderRef = ""
+ self.transmit = True # if false, order will be created but not transmitted
+ self.parentId = 0 # Parent order id, to associate Auto STP or TRAIL orders with the original order.
+ self.blockOrder = False
+ self.sweepToFill = False
+ self.displaySize = 0
+ self.triggerMethod = 0 # 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point
+ self.outsideRth = False
+ self.hidden = False
+ self.goodAfterTime = "" # Format: 20060505 08:00:00 {time zone}
+ self.goodTillDate = "" # Format: 20060505 08:00:00 {time zone}
+ self.rule80A = "" # Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N'
+ self.allOrNone = False
+ self.minQty = UNSET_INTEGER # type: int
+ self.percentOffset = UNSET_DOUBLE # type: float # REL orders only
+ self.overridePercentageConstraints = False
+ self.trailStopPrice = UNSET_DOUBLE # type: float
+ self.trailingPercent = UNSET_DOUBLE # type: float # TRAILLIMIT orders only
+
+ # financial advisors only
+ self.faGroup = ""
+ self.faMethod = ""
+ self.faPercentage = ""
+
+ # institutional (ie non-cleared) only
+ self.designatedLocation = "" # used only when shortSaleSlot=2
+ self.openClose = "" # O=Open, C=Close
+ self.origin = CUSTOMER # 0=Customer, 1=Firm
+ self.shortSaleSlot = (
+ 0
+ ) # type: int # 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action=SSHORT
+ self.exemptCode = -1
+
+ # SMART routing only
+ self.discretionaryAmt = 0
+ self.optOutSmartRouting = False
+
+ # BOX exchange orders only
+ self.auctionStrategy = (
+ AUCTION_UNSET
+ ) # type: int # AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT
+ self.startingPrice = UNSET_DOUBLE # type: float
+ self.stockRefPrice = UNSET_DOUBLE # type: float
+ self.delta = UNSET_DOUBLE # type: float
+
+ # pegged to stock and VOL orders only
+ self.stockRangeLower = UNSET_DOUBLE # type: float
+ self.stockRangeUpper = UNSET_DOUBLE # type: float
+
+ self.randomizePrice = False
+ self.randomizeSize = False
+
+ # VOLATILITY ORDERS ONLY
+ self.volatility = UNSET_DOUBLE # type: float
+ self.volatilityType = UNSET_INTEGER # type: int # 1=daily, 2=annual
+ self.deltaNeutralOrderType = ""
+ self.deltaNeutralAuxPrice = UNSET_DOUBLE # type: float
+ self.deltaNeutralConId = 0
+ self.deltaNeutralSettlingFirm = ""
+ self.deltaNeutralClearingAccount = ""
+ self.deltaNeutralClearingIntent = ""
+ self.deltaNeutralOpenClose = ""
+ self.deltaNeutralShortSale = False
+ self.deltaNeutralShortSaleSlot = 0
+ self.deltaNeutralDesignatedLocation = ""
+ self.continuousUpdate = False
+ self.referencePriceType = UNSET_INTEGER # type: int # 1=Average, 2 = BidOrAsk
+
+ # COMBO ORDERS ONLY
+ self.basisPoints = UNSET_DOUBLE # type: float # EFP orders only
+ self.basisPointsType = UNSET_INTEGER # type: int # EFP orders only
+
+ # SCALE ORDERS ONLY
+ self.scaleInitLevelSize = UNSET_INTEGER # type: int
+ self.scaleSubsLevelSize = UNSET_INTEGER # type: int
+ self.scalePriceIncrement = UNSET_DOUBLE # type: float
+ self.scalePriceAdjustValue = UNSET_DOUBLE # type: float
+ self.scalePriceAdjustInterval = UNSET_INTEGER # type: int
+ self.scaleProfitOffset = UNSET_DOUBLE # type: float
+ self.scaleAutoReset = False
+ self.scaleInitPosition = UNSET_INTEGER # type: int
+ self.scaleInitFillQty = UNSET_INTEGER # type: int
+ self.scaleRandomPercent = False
+ self.scaleTable = ""
+
+ # HEDGE ORDERS
+ self.hedgeType = "" # 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair
+ self.hedgeParam = "" # 'beta=X' value for beta hedge, 'ratio=Y' for pair hedge
+
+ # Clearing info
+ self.account = "" # IB account
+ self.settlingFirm = ""
+ self.clearingAccount = "" # True beneficiary of the order
+ self.clearingIntent = "" # "" (Default), "IB", "Away", "PTA" (PostTrade)
+
+ # ALGO ORDERS ONLY
+ self.algoStrategy = ""
+
+ self.algoParams = None # TagValueList
+ self.smartComboRoutingParams = None # TagValueList
+
+ self.algoId = ""
+
+ # What-if
+ self.whatIf = False
+
+ # Not Held
+ self.notHeld = False
+ self.solicited = False
+
+ # models
+ self.modelCode = ""
+
+ # order combo legs
+
+ self.orderComboLegs = None # OrderComboLegListSPtr
+
+ self.orderMiscOptions = None # TagValueList
+
+ # VER PEG2BENCH fields:
+ self.referenceContractId = 0
+ self.peggedChangeAmount = 0.0
+ self.isPeggedChangeAmountDecrease = False
+ self.referenceChangeAmount = 0.0
+ self.referenceExchangeId = ""
+ self.adjustedOrderType = ""
+
+ self.triggerPrice = UNSET_DOUBLE
+ self.adjustedStopPrice = UNSET_DOUBLE
+ self.adjustedStopLimitPrice = UNSET_DOUBLE
+ self.adjustedTrailingAmount = UNSET_DOUBLE
+ self.adjustableTrailingUnit = 0
+ self.lmtPriceOffset = UNSET_DOUBLE
+
+ self.conditions = [] # std::vector>
+ self.conditionsCancelOrder = False
+ self.conditionsIgnoreRth = False
+
+ # ext operator
+ self.extOperator = ""
+
+ # native cash quantity
+ self.cashQty = UNSET_DOUBLE
+
+ self.mifid2DecisionMaker = ""
+ self.mifid2DecisionAlgo = ""
+ self.mifid2ExecutionTrader = ""
+ self.mifid2ExecutionAlgo = ""
+
+ self.dontUseAutoPriceForHedge = False
+
+ self.isOmsContainer = False
+
+ self.discretionaryUpToLimitPrice = False
+
+ self.autoCancelDate = ""
+ self.filledQuantity = UNSET_DECIMAL
+ self.refFuturesConId = 0
+ self.autoCancelParent = False
+ self.shareholder = ""
+ self.imbalanceOnly = False
+ self.routeMarketableToBbo = None
+ self.parentPermId = 0
+
+ self.usePriceMgmtAlgo = None
+ self.duration = UNSET_INTEGER
+ self.postToAts = UNSET_INTEGER
+ self.advancedErrorOverride = ""
+ self.manualOrderTime = ""
+ self.minTradeQty = UNSET_INTEGER
+ self.minCompeteSize = UNSET_INTEGER
+ self.competeAgainstBestOffset = UNSET_DOUBLE
+ self.midOffsetAtWhole = UNSET_DOUBLE
+ self.midOffsetAtHalf = UNSET_DOUBLE
+ self.customerAccount = ""
+ self.professionalCustomer = False
+ self.bondAccruedInterest = ""
+ self.includeOvernight = False
+ self.manualOrderIndicator = UNSET_INTEGER
+ self.submitter = ""
+ self.postOnly = False
+ self.allowPreOpen = False
+ self.ignoreOpenAuction = False
+ self.deactivate = False
+ self.seekPriceImprovement = None
+ self.whatIfType = UNSET_INTEGER
+
+ # attached orders
+ self.slOrderId = UNSET_INTEGER
+ self.slOrderType = ""
+ self.ptOrderId = UNSET_INTEGER
+ self.ptOrderType = ""
+
+ def __str__(self):
+ s = "%s,%s,%s:" % (
+ intMaxString(self.orderId),
+ intMaxString(self.clientId),
+ longMaxString(self.permId),
+ )
+
+ s += " %s %s %s@%s" % (
+ self.orderType,
+ self.action,
+ decimalMaxString(self.totalQuantity),
+ floatMaxString(self.lmtPrice),
+ )
+
+ s += f" {self.tif}"
+
+ if self.orderComboLegs:
+ s += " CMB("
+ for leg in self.orderComboLegs:
+ s += str(leg) + ","
+ s += ")"
+
+ if self.conditions:
+ s += " COND("
+ for cond in self.conditions:
+ s += str(cond) + ","
+ s += ")"
+
+ return s
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/order_cancel.py b/packages/ibkr/ref/source/pythonclient/ibapi/order_cancel.py
new file mode 100644
index 00000000..16ff8cd0
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/order_cancel.py
@@ -0,0 +1,21 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.const import UNSET_INTEGER
+from ibapi.object_implem import Object
+from ibapi.utils import intMaxString
+
+class OrderCancel(Object):
+ def __init__(self):
+ self.manualOrderCancelTime = ""
+ self.extOperator = ""
+ self.manualOrderIndicator = UNSET_INTEGER
+
+ def __str__(self):
+ s = "manualOrderCancelTime: %s, extOperator: %s, manualOrderIndicator: %s" % (
+ self.manualOrderCancelTime, self.extOperator, intMaxString(self.manualOrderIndicator)
+ )
+
+ return s
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/order_condition.py b/packages/ibkr/ref/source/pythonclient/ibapi/order_condition.py
new file mode 100644
index 00000000..59ea4a6b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/order_condition.py
@@ -0,0 +1,289 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi import comm
+from ibapi.const import UNSET_DOUBLE
+from ibapi.object_implem import Object
+from ibapi.enum_implem import Enum
+from ibapi.utils import decode
+
+
+# TODO: add support for Rebate, P/L, ShortableShares conditions
+
+
+class OrderCondition(Object):
+ Price = 1
+ Time = 3
+ Margin = 4
+ Execution = 5
+ Volume = 6
+ PercentChange = 7
+
+ def __init__(self, condType):
+ self.condType = condType
+ self.isConjunctionConnection = True
+
+ def type(self):
+ return self.condType
+
+ def And(self):
+ self.isConjunctionConnection = True
+ return self
+
+ def Or(self):
+ self.isConjunctionConnection = False
+ return self
+
+ def decode(self, fields):
+ connector = decode(str, fields)
+ self.isConjunctionConnection = connector == "a"
+
+ def make_fields(self):
+ return [comm.make_field("a" if self.isConjunctionConnection else "o")]
+
+ def __str__(self):
+ return "" if self.isConjunctionConnection else ""
+
+
+class ExecutionCondition(OrderCondition):
+ def __init__(self, secType=None, exch=None, symbol=None):
+ OrderCondition.__init__(self, OrderCondition.Execution)
+ self.secType = secType
+ self.exchange = exch
+ self.symbol = symbol
+
+ def decode(self, fields):
+ OrderCondition.decode(self, fields)
+ self.secType = decode(str, fields)
+ self.exchange = decode(str, fields)
+ self.symbol = decode(str, fields)
+
+ def make_fields(self):
+ flds = OrderCondition.make_fields(self) + [
+ comm.make_field(self.secType),
+ comm.make_field(self.exchange),
+ comm.make_field(self.symbol),
+ ]
+ return flds
+
+ def __str__(self):
+ return (
+ "trade occurs for "
+ + self.symbol
+ + " symbol on "
+ + self.exchange
+ + " exchange for "
+ + self.secType
+ + " security type"
+ )
+
+
+class OperatorCondition(OrderCondition):
+ def __init__(self, condType=None, isMore=None):
+ OrderCondition.__init__(self, condType)
+ self.isMore = isMore
+
+ def valueToString(self) -> str:
+ raise NotImplementedError("abstractmethod!")
+
+ def setValueFromString(self, text: str) -> None:
+ raise NotImplementedError("abstractmethod!")
+
+ def decode(self, fields):
+ OrderCondition.decode(self, fields)
+ self.isMore = decode(bool, fields)
+ text = decode(str, fields)
+ self.setValueFromString(text)
+
+ def make_fields(self):
+ return OrderCondition.make_fields(self) + [
+ comm.make_field(self.isMore),
+ comm.make_field(self.valueToString()),
+ ]
+
+ def __str__(self):
+ sb = ">= " if self.isMore else "<= "
+ return f" {sb} {self.valueToString()}"
+
+
+class MarginCondition(OperatorCondition):
+ def __init__(self, isMore=None, percent=None):
+ OperatorCondition.__init__(self, OrderCondition.Margin, isMore)
+ self.percent = percent
+
+ def decode(self, fields):
+ OperatorCondition.decode(self, fields)
+
+ def make_fields(self):
+ flds = OperatorCondition.make_fields(self)
+ return flds
+
+ def valueToString(self) -> str:
+ return str(self.percent)
+
+ def setValueFromString(self, text: str) -> None:
+ self.percent = float(text)
+
+ def __str__(self):
+ return f"the margin cushion percent {OperatorCondition.__str__(self)} "
+
+
+class ContractCondition(OperatorCondition):
+ def __init__(self, condType=None, conId=None, exch=None, isMore=None):
+ OperatorCondition.__init__(self, condType, isMore)
+ self.conId = conId
+ self.exchange = exch
+
+ def decode(self, fields):
+ OperatorCondition.decode(self, fields)
+ self.conId = decode(int, fields)
+ self.exchange = decode(str, fields)
+
+ def make_fields(self):
+ return OperatorCondition.make_fields(self) + [
+ comm.make_field(self.conId),
+ comm.make_field(self.exchange),
+ ]
+
+ def valueToString(self) -> str:
+ # todo
+ pass
+
+ def setValueFromString(self, text: str) -> None:
+ # todo
+ pass
+
+ def __str__(self):
+ return f"{self.conId} on {self.exchange} is {OperatorCondition.__str__(self)} "
+
+
+class TimeCondition(OperatorCondition):
+ def __init__(self, isMore=None, time=None):
+ OperatorCondition.__init__(self, OrderCondition.Time, isMore)
+ self.time = time
+
+ def decode(self, fields):
+ OperatorCondition.decode(self, fields)
+
+ def make_fields(self):
+ flds = OperatorCondition.make_fields(self)
+ return flds
+
+ def valueToString(self) -> str:
+ return self.time
+
+ def setValueFromString(self, text: str) -> None:
+ self.time = text
+
+ def __str__(self):
+ return f"time is {OperatorCondition.__str__(self)} "
+
+
+class PriceCondition(ContractCondition):
+ TriggerMethodEnum = Enum(
+ "Default", # = 0,
+ "DoubleBidAsk", # = 1,
+ "Last", # = 2,
+ "DoubleLast", # = 3,
+ "BidAsk", # = 4,
+ "N/A1",
+ "N/A2",
+ "LastBidAsk", # = 7,
+ "MidPoint",
+ ) # = 8
+
+ def __init__(
+ self, triggerMethod=None, conId=None, exch=None, isMore=None, price=None
+ ):
+ ContractCondition.__init__(self, OrderCondition.Price, conId, exch, isMore)
+ self.price = price
+ self.triggerMethod = triggerMethod
+
+ def decode(self, fields):
+ ContractCondition.decode(self, fields)
+ self.triggerMethod = decode(int, fields)
+
+ def make_fields(self):
+ flds = ContractCondition.make_fields(self) + [
+ comm.make_field(self.triggerMethod),
+ ]
+ return flds
+
+ def valueToString(self) -> str:
+ return str(self.price)
+
+ def setValueFromString(self, text: str) -> None:
+ self.price = float(text)
+
+ def __str__(self):
+ return (
+ f"{PriceCondition.TriggerMethodEnum.toStr(self.triggerMethod)} "
+ f"price of {ContractCondition.__str__(self)} "
+ )
+
+
+class PercentChangeCondition(ContractCondition):
+ def __init__(self, conId=None, exch=None, isMore=None, changePercent=UNSET_DOUBLE):
+ ContractCondition.__init__(
+ self, OrderCondition.PercentChange, conId, exch, isMore
+ )
+ self.changePercent = changePercent
+
+ def decode(self, fields):
+ ContractCondition.decode(self, fields)
+
+ def make_fields(self):
+ flds = ContractCondition.make_fields(self)
+ return flds
+
+ def valueToString(self) -> str:
+ return str(self.changePercent)
+
+ def setValueFromString(self, text: str) -> None:
+ self.changePercent = float(text)
+
+ def __str__(self):
+ return f"percent change of {ContractCondition.__str__(self)} "
+
+
+class VolumeCondition(ContractCondition):
+ def __init__(self, conId=None, exch=None, isMore=None, volume=None):
+ ContractCondition.__init__(self, OrderCondition.Volume, conId, exch, isMore)
+ self.volume = volume
+
+ def decode(self, fields):
+ ContractCondition.decode(self, fields)
+
+ def make_fields(self):
+ flds = ContractCondition.make_fields(self)
+ return flds
+
+ def valueToString(self) -> str:
+ return str(self.volume)
+
+ def setValueFromString(self, text: str) -> None:
+ self.volume = int(text)
+
+ def __str__(self):
+ return f"volume of {ContractCondition.__str__(self)} "
+
+
+def Create(condType):
+ cond = None
+
+ if OrderCondition.Execution == condType:
+ cond = ExecutionCondition()
+ elif OrderCondition.Margin == condType:
+ cond = MarginCondition()
+ elif OrderCondition.PercentChange == condType:
+ cond = PercentChangeCondition()
+ elif OrderCondition.Price == condType:
+ cond = PriceCondition()
+ elif OrderCondition.Time == condType:
+ cond = TimeCondition()
+ elif OrderCondition.Volume == condType:
+ cond = VolumeCondition()
+
+ return cond
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/order_state.py b/packages/ibkr/ref/source/pythonclient/ibapi/order_state.py
new file mode 100644
index 00000000..995bca8d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/order_state.py
@@ -0,0 +1,117 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.object_implem import Object
+from ibapi.const import UNSET_DOUBLE, UNSET_DECIMAL
+from ibapi.utils import decimalMaxString
+from ibapi.utils import floatMaxString
+
+class OrderAllocation(Object):
+ def __init__(self):
+ self.account = ""
+ self.position = UNSET_DECIMAL
+ self.positionDesired = UNSET_DECIMAL
+ self.positionAfter = UNSET_DECIMAL
+ self.desiredAllocQty = UNSET_DECIMAL
+ self.allowedAllocQty = UNSET_DECIMAL
+ self.isMonetary = False
+
+ def __str__(self):
+ s = ("Account: %s, Position: %s, PositionDesired: %s, PositionAfter: %s, "
+ "DesiredAllocQty: %s, AllowedAllocQty: %s, IsMonetary: %s") % (
+ str(self.account),
+ decimalMaxString(self.position),
+ decimalMaxString(self.positionDesired),
+ decimalMaxString(self.positionAfter),
+ decimalMaxString(self.desiredAllocQty),
+ decimalMaxString(self.allowedAllocQty),
+ str(self.isMonetary),
+ )
+ return s
+
+class OrderState:
+ def __init__(self):
+ self.status = ""
+
+ self.initMarginBefore = ""
+ self.maintMarginBefore = ""
+ self.equityWithLoanBefore = ""
+ self.initMarginChange = ""
+ self.maintMarginChange = ""
+ self.equityWithLoanChange = ""
+ self.initMarginAfter = ""
+ self.maintMarginAfter = ""
+ self.equityWithLoanAfter = ""
+
+ self.commissionAndFees = UNSET_DOUBLE # type: float
+ self.minCommissionAndFees = UNSET_DOUBLE # type: float
+ self.maxCommissionAndFees = UNSET_DOUBLE # type: float
+ self.commissionAndFeesCurrency = ""
+ self.marginCurrency = ""
+ self.initMarginBeforeOutsideRTH = UNSET_DOUBLE # type: float
+ self.maintMarginBeforeOutsideRTH = UNSET_DOUBLE # type: float
+ self.equityWithLoanBeforeOutsideRTH = UNSET_DOUBLE # type: float
+ self.initMarginChangeOutsideRTH = UNSET_DOUBLE # type: float
+ self.maintMarginChangeOutsideRTH = UNSET_DOUBLE # type: float
+ self.equityWithLoanChangeOutsideRTH = UNSET_DOUBLE # type: float
+ self.initMarginAfterOutsideRTH = UNSET_DOUBLE # type: float
+ self.maintMarginAfterOutsideRTH = UNSET_DOUBLE # type: float
+ self.equityWithLoanAfterOutsideRTH = UNSET_DOUBLE # type: float
+ self.suggestedSize = UNSET_DECIMAL
+ self.rejectReason = ""
+ self.orderAllocations = None
+ self.warningText = ""
+ self.completedTime = ""
+ self.completedStatus = ""
+
+ def __str__(self):
+ s = ("Status: %s, InitMarginBefore: %s, MaintMarginBefore: %s, EquityWithLoanBefore: %s, "
+ "InitMarginChange: %s, MaintMarginChange: %s, EquityWithLoanChange: %s, "
+ "InitMarginAfter: %s, MaintMarginAfter: %s, EquityWithLoanAfter: %s, "
+ "CommissionAndFees: %s, MinCommissionAndFees: %s, MaxCommissionAndFees: %s, CommissionAndFeesCurrency: %s, MarginCurrency: %s, "
+ "InitMarginBeforeOutsideRTH: %s, MaintMarginBeforeOutsideRTH: %s, EquityWithLoanBeforeOutsideRTH: %s, "
+ "InitMarginChangeOutsideRTH: %s, MaintMarginChangeOutsideRTH: %s, equityWithLoanChangeOutsideRTH: %s, "
+ "InitMarginAfterOutsideRTH: %s, MaintMarginAfterOutsideRTH: %s, equityWithLoanAfterOutsideRTH: %s, "
+ "SuggestedSize: %s, RejectReason: %s, WarningText: %s, CompletedTime: %s, CompletedStatus: %s") % (
+ str(self.status),
+ str(self.initMarginBefore),
+ str(self.maintMarginBefore),
+ str(self.equityWithLoanBefore),
+ str(self.initMarginChange),
+ str(self.maintMarginChange),
+ str(self.equityWithLoanChange),
+ str(self.initMarginAfter),
+ str(self.maintMarginAfter),
+ str(self.equityWithLoanAfter),
+ floatMaxString(self.commissionAndFees),
+ floatMaxString(self.minCommissionAndFees),
+ floatMaxString(self.maxCommissionAndFees),
+ str(self.commissionAndFeesCurrency),
+ str(self.marginCurrency),
+ floatMaxString(self.initMarginBeforeOutsideRTH),
+ floatMaxString(self.maintMarginBeforeOutsideRTH),
+ floatMaxString(self.equityWithLoanBeforeOutsideRTH),
+ floatMaxString(self.initMarginChangeOutsideRTH),
+ floatMaxString(self.maintMarginChangeOutsideRTH),
+ floatMaxString(self.equityWithLoanChangeOutsideRTH),
+ floatMaxString(self.initMarginAfterOutsideRTH),
+ floatMaxString(self.maintMarginAfterOutsideRTH),
+ floatMaxString(self.equityWithLoanAfterOutsideRTH),
+ decimalMaxString(self.suggestedSize),
+ str(self.rejectReason),
+ str(self.warningText),
+ str(self.completedTime),
+ str(self.completedStatus),
+ )
+
+
+ if self.orderAllocations:
+ s += " OrderAllocations("
+ for orderAllocation in self.orderAllocations:
+ s += str(orderAllocation) + "; "
+ s += ")"
+
+ return s
+
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/orderdecoder.py b/packages/ibkr/ref/source/pythonclient/ibapi/orderdecoder.py
new file mode 100644
index 00000000..f0020a0e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/orderdecoder.py
@@ -0,0 +1,539 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+import logging
+from _decimal import Decimal
+
+from ibapi import order_condition
+from ibapi.const import UNSET_DOUBLE
+from ibapi.object_implem import Object
+from ibapi.order import OrderComboLeg
+from ibapi.order_state import OrderAllocation
+from ibapi.contract import ComboLeg
+from ibapi.server_versions import (
+ MIN_SERVER_VER_FA_PROFILE_DESUPPORT,
+ MIN_SERVER_VER_MODELS_SUPPORT,
+ MIN_SERVER_VER_SSHORTX_OLD,
+ MIN_SERVER_VER_WHAT_IF_EXT_FIELDS,
+ MIN_SERVER_VER_PEGGED_TO_BENCHMARK,
+ MIN_SERVER_VER_SOFT_DOLLAR_TIER,
+ MIN_SERVER_VER_CASH_QTY,
+ MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE,
+ MIN_SERVER_VER_ORDER_CONTAINER,
+ MIN_SERVER_VER_D_PEG_ORDERS,
+ MIN_CLIENT_VER,
+ MIN_SERVER_VER_PRICE_MGMT_ALGO,
+ MIN_SERVER_VER_DURATION,
+ MIN_SERVER_VER_POST_TO_ATS,
+ MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS,
+ MIN_SERVER_VER_CUSTOMER_ACCOUNT,
+ MIN_SERVER_VER_PROFESSIONAL_CUSTOMER,
+ MIN_SERVER_VER_BOND_ACCRUED_INTEREST,
+ MIN_SERVER_VER_INCLUDE_OVERNIGHT,
+ MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER,
+ MIN_SERVER_VER_FULL_ORDER_PREVIEW_FIELDS,
+ MIN_SERVER_VER_SUBMITTER
+)
+from ibapi.tag_value import TagValue
+from ibapi.utils import decode, SHOW_UNSET, isPegBenchOrder
+from ibapi.wrapper import DeltaNeutralContract
+from ibapi.softdollartier import SoftDollarTier
+
+logger = logging.getLogger(__name__)
+
+
+class OrderDecoder(Object):
+ def __init__(self, contract, order, orderState, version, serverVersion):
+ self.contract = contract
+ self.order = order
+ self.orderState = orderState
+ self.version = version
+ self.serverVersion = serverVersion
+
+ def decodeOrderId(self, fields):
+ self.order.orderId = decode(int, fields)
+
+ def decodeContractFields(self, fields):
+ self.contract.conId = decode(int, fields)
+ self.contract.symbol = decode(str, fields)
+ self.contract.secType = decode(str, fields)
+ self.contract.lastTradeDateOrContractMonth = decode(str, fields)
+ self.contract.strike = decode(float, fields)
+ self.contract.right = decode(str, fields)
+ if self.version >= 32:
+ self.contract.multiplier = decode(str, fields)
+ self.contract.exchange = decode(str, fields)
+ self.contract.currency = decode(str, fields)
+ self.contract.localSymbol = decode(str, fields)
+ if self.version >= 32:
+ self.contract.tradingClass = decode(str, fields)
+
+ def decodeAction(self, fields):
+ self.order.action = decode(str, fields)
+
+ def decodeTotalQuantity(self, fields):
+ self.order.totalQuantity = decode(Decimal, fields)
+
+ def decodeOrderType(self, fields):
+ self.order.orderType = decode(str, fields)
+
+ def decodeLmtPrice(self, fields):
+ if self.version < 29:
+ self.order.lmtPrice = decode(float, fields)
+ else:
+ self.order.lmtPrice = decode(float, fields, SHOW_UNSET)
+
+ def decodeAuxPrice(self, fields):
+ if self.version < 30:
+ self.order.auxPrice = decode(float, fields)
+ else:
+ self.order.auxPrice = decode(float, fields, SHOW_UNSET)
+
+ def decodeTIF(self, fields):
+ self.order.tif = decode(str, fields)
+
+ def decodeOcaGroup(self, fields):
+ self.order.ocaGroup = decode(str, fields)
+
+ def decodeAccount(self, fields):
+ self.order.account = decode(str, fields)
+
+ def decodeOpenClose(self, fields):
+ self.order.openClose = decode(str, fields)
+
+ def decodeOrigin(self, fields):
+ self.order.origin = decode(int, fields)
+
+ def decodeOrderRef(self, fields):
+ self.order.orderRef = decode(str, fields)
+
+ def decodeClientId(self, fields):
+ self.order.clientId = decode(int, fields)
+
+ def decodePermId(self, fields):
+ self.order.permId = decode(int, fields)
+
+ def decodeOutsideRth(self, fields):
+ self.order.outsideRth = decode(bool, fields)
+
+ def decodeHidden(self, fields):
+ self.order.hidden = decode(bool, fields)
+
+ def decodeDiscretionaryAmt(self, fields):
+ self.order.discretionaryAmt = decode(float, fields)
+
+ def decodeGoodAfterTime(self, fields):
+ self.order.goodAfterTime = decode(str, fields)
+
+ def skipSharesAllocation(self, fields):
+ _sharesAllocation = decode(str, fields) # deprecated
+
+ def decodeFAParams(self, fields):
+ self.order.faGroup = decode(str, fields)
+ self.order.faMethod = decode(str, fields)
+ self.order.faPercentage = decode(str, fields)
+ if self.serverVersion < MIN_SERVER_VER_FA_PROFILE_DESUPPORT:
+ _faProfile = decode(str, fields) # skip deprecated faProfile field
+
+ def decodeModelCode(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT:
+ self.order.modelCode = decode(str, fields)
+
+ def decodeGoodTillDate(self, fields):
+ self.order.goodTillDate = decode(str, fields)
+
+ def decodeRule80A(self, fields):
+ self.order.rule80A = decode(str, fields)
+
+ def decodePercentOffset(self, fields):
+ self.order.percentOffset = decode(float, fields, SHOW_UNSET)
+
+ def decodeSettlingFirm(self, fields):
+ self.order.settlingFirm = decode(str, fields)
+
+ def decodeShortSaleParams(self, fields):
+ self.order.shortSaleSlot = decode(int, fields)
+ self.order.designatedLocation = decode(str, fields)
+ if self.serverVersion == MIN_SERVER_VER_SSHORTX_OLD:
+ decode(int, fields)
+ elif self.version >= 23:
+ self.order.exemptCode = decode(int, fields)
+
+ def decodeAuctionStrategy(self, fields):
+ self.order.auctionStrategy = decode(int, fields)
+
+ def decodeBoxOrderParams(self, fields):
+ self.order.startingPrice = decode(float, fields, SHOW_UNSET)
+ self.order.stockRefPrice = decode(float, fields, SHOW_UNSET)
+ self.order.delta = decode(float, fields, SHOW_UNSET)
+
+ def decodePegToStkOrVolOrderParams(self, fields):
+ self.order.stockRangeLower = decode(float, fields, SHOW_UNSET)
+ self.order.stockRangeUpper = decode(float, fields, SHOW_UNSET)
+
+ def decodeDisplaySize(self, fields):
+ self.order.displaySize = decode(int, fields, SHOW_UNSET)
+
+ def decodeBlockOrder(self, fields):
+ self.order.blockOrder = decode(bool, fields)
+
+ def decodeSweepToFill(self, fields):
+ self.order.sweepToFill = decode(bool, fields)
+
+ def decodeAllOrNone(self, fields):
+ self.order.allOrNone = decode(bool, fields)
+
+ def decodeMinQty(self, fields):
+ self.order.minQty = decode(int, fields, SHOW_UNSET)
+
+ def decodeOcaType(self, fields):
+ self.order.ocaType = decode(int, fields)
+
+ def skipETradeOnly(self, fields):
+ _eTradeOnly = decode(bool, fields) # deprecated
+
+ def skipFirmQuoteOnly(self, fields):
+ _firmQuoteOnly = decode(bool, fields) # ` deprecated
+
+ def skipNbboPriceCap(self, fields):
+ _nbboPriceCap = decode(float, fields, SHOW_UNSET) # deprecated
+
+ def decodeParentId(self, fields):
+ self.order.parentId = decode(int, fields)
+
+ def decodeTriggerMethod(self, fields):
+ self.order.triggerMethod = decode(int, fields)
+
+ def decodeVolOrderParams(self, fields, readOpenOrderAttribs):
+ self.order.volatility = decode(float, fields, SHOW_UNSET)
+ self.order.volatilityType = decode(int, fields)
+ self.order.deltaNeutralOrderType = decode(str, fields)
+ self.order.deltaNeutralAuxPrice = decode(float, fields, SHOW_UNSET)
+
+ if self.version >= 27 and self.order.deltaNeutralOrderType:
+ self.order.deltaNeutralConId = decode(int, fields)
+ if readOpenOrderAttribs:
+ self.order.deltaNeutralSettlingFirm = decode(str, fields)
+ self.order.deltaNeutralClearingAccount = decode(str, fields)
+ self.order.deltaNeutralClearingIntent = decode(str, fields)
+
+ if self.version >= 31 and self.order.deltaNeutralOrderType:
+ if readOpenOrderAttribs:
+ self.order.deltaNeutralOpenClose = decode(str, fields)
+ self.order.deltaNeutralShortSale = decode(bool, fields)
+ self.order.deltaNeutralShortSaleSlot = decode(int, fields)
+ self.order.deltaNeutralDesignatedLocation = decode(str, fields)
+
+ self.order.continuousUpdate = decode(bool, fields)
+ self.order.referencePriceType = decode(int, fields)
+
+ def decodeTrailParams(self, fields):
+ self.order.trailStopPrice = decode(float, fields, SHOW_UNSET)
+ if self.version >= 30:
+ self.order.trailingPercent = decode(float, fields, SHOW_UNSET)
+
+ def decodeBasisPoints(self, fields):
+ self.order.basisPoints = decode(float, fields, SHOW_UNSET)
+ self.order.basisPointsType = decode(int, fields, SHOW_UNSET)
+
+ def decodeComboLegs(self, fields):
+ self.contract.comboLegsDescrip = decode(str, fields)
+
+ if self.version >= 29:
+ comboLegsCount = decode(int, fields)
+
+ if comboLegsCount > 0:
+ self.contract.comboLegs = []
+ for _ in range(comboLegsCount):
+ comboLeg = ComboLeg()
+ comboLeg.conId = decode(int, fields)
+ comboLeg.ratio = decode(int, fields)
+ comboLeg.action = decode(str, fields)
+ comboLeg.exchange = decode(str, fields)
+ comboLeg.openClose = decode(int, fields)
+ comboLeg.shortSaleSlot = decode(int, fields)
+ comboLeg.designatedLocation = decode(str, fields)
+ comboLeg.exemptCode = decode(int, fields)
+ self.contract.comboLegs.append(comboLeg)
+
+ orderComboLegsCount = decode(int, fields)
+ if orderComboLegsCount > 0:
+ self.order.orderComboLegs = []
+ for _ in range(orderComboLegsCount):
+ orderComboLeg = OrderComboLeg()
+ orderComboLeg.price = decode(float, fields, SHOW_UNSET)
+ self.order.orderComboLegs.append(orderComboLeg)
+
+ def decodeSmartComboRoutingParams(self, fields):
+ if self.version >= 26:
+ smartComboRoutingParamsCount = decode(int, fields)
+ if smartComboRoutingParamsCount > 0:
+ self.order.smartComboRoutingParams = []
+ for _ in range(smartComboRoutingParamsCount):
+ tagValue = TagValue()
+ tagValue.tag = decode(str, fields)
+ tagValue.value = decode(str, fields)
+ self.order.smartComboRoutingParams.append(tagValue)
+
+ def decodeScaleOrderParams(self, fields):
+ if self.version >= 20:
+ self.order.scaleInitLevelSize = decode(int, fields, SHOW_UNSET)
+ self.order.scaleSubsLevelSize = decode(int, fields, SHOW_UNSET)
+ else:
+ self.order.notSuppScaleNumComponents = decode(int, fields, SHOW_UNSET)
+ self.order.scaleInitLevelSize = decode(int, fields, SHOW_UNSET)
+
+ self.order.scalePriceIncrement = decode(float, fields, SHOW_UNSET)
+
+ if (
+ self.version >= 28
+ and self.order.scalePriceIncrement != UNSET_DOUBLE
+ and self.order.scalePriceIncrement > 0.0
+ ):
+ self.order.scalePriceAdjustValue = decode(float, fields, SHOW_UNSET)
+ self.order.scalePriceAdjustInterval = decode(int, fields, SHOW_UNSET)
+ self.order.scaleProfitOffset = decode(float, fields, SHOW_UNSET)
+ self.order.scaleAutoReset = decode(bool, fields)
+ self.order.scaleInitPosition = decode(int, fields, SHOW_UNSET)
+ self.order.scaleInitFillQty = decode(int, fields, SHOW_UNSET)
+ self.order.scaleRandomPercent = decode(bool, fields)
+
+ def decodeHedgeParams(self, fields):
+ if self.version >= 24:
+ self.order.hedgeType = decode(str, fields)
+ if self.order.hedgeType:
+ self.order.hedgeParam = decode(str, fields)
+
+ def decodeOptOutSmartRouting(self, fields):
+ if self.version >= 25:
+ self.order.optOutSmartRouting = decode(bool, fields)
+
+ def decodeClearingParams(self, fields):
+ self.order.clearingAccount = decode(str, fields)
+ self.order.clearingIntent = decode(str, fields)
+
+ def decodeNotHeld(self, fields):
+ if self.version >= 22:
+ self.order.notHeld = decode(bool, fields)
+
+ def decodeDeltaNeutral(self, fields):
+ if self.version >= 20:
+ deltaNeutralContractPresent = decode(bool, fields)
+ if deltaNeutralContractPresent:
+ self.contract.deltaNeutralContract = DeltaNeutralContract()
+ self.contract.deltaNeutralContract.conId = decode(int, fields)
+ self.contract.deltaNeutralContract.delta = decode(float, fields)
+ self.contract.deltaNeutralContract.price = decode(float, fields)
+
+ def decodeAlgoParams(self, fields):
+ if self.version >= 21:
+ self.order.algoStrategy = decode(str, fields)
+ if self.order.algoStrategy:
+ algoParamsCount = decode(int, fields)
+ if algoParamsCount > 0:
+ self.order.algoParams = []
+ for _ in range(algoParamsCount):
+ tagValue = TagValue()
+ tagValue.tag = decode(str, fields)
+ tagValue.value = decode(str, fields)
+ self.order.algoParams.append(tagValue)
+
+ def decodeSolicited(self, fields):
+ if self.version >= 33:
+ self.order.solicited = decode(bool, fields)
+
+ def decodeOrderStatus(self, fields):
+ self.orderState.status = decode(str, fields)
+
+ def decodeWhatIfInfoAndCommissionAndFees(self, fields):
+ self.order.whatIf = decode(bool, fields)
+ OrderDecoder.decodeOrderStatus(self, fields)
+ if self.serverVersion >= MIN_SERVER_VER_WHAT_IF_EXT_FIELDS:
+ self.orderState.initMarginBefore = decode(str, fields)
+ self.orderState.maintMarginBefore = decode(str, fields)
+ self.orderState.equityWithLoanBefore = decode(str, fields)
+ self.orderState.initMarginChange = decode(str, fields)
+ self.orderState.maintMarginChange = decode(str, fields)
+ self.orderState.equityWithLoanChange = decode(str, fields)
+
+ self.orderState.initMarginAfter = decode(str, fields)
+ self.orderState.maintMarginAfter = decode(str, fields)
+ self.orderState.equityWithLoanAfter = decode(str, fields)
+
+ self.orderState.commissionAndFees = decode(float, fields, SHOW_UNSET)
+ self.orderState.minCommissionAndFees = decode(float, fields, SHOW_UNSET)
+ self.orderState.maxCommissionAndFees = decode(float, fields, SHOW_UNSET)
+ self.orderState.commissionAndFeesCurrency = decode(str, fields)
+
+ if self.serverVersion >= MIN_SERVER_VER_FULL_ORDER_PREVIEW_FIELDS:
+ self.orderState.marginCurrency = decode(str, fields)
+ self.orderState.initMarginBeforeOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.maintMarginBeforeOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.equityWithLoanBeforeOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.initMarginChangeOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.maintMarginChangeOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.equityWithLoanChangeOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.initMarginAfterOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.maintMarginAfterOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.equityWithLoanAfterOutsideRTH = decode(float, fields, SHOW_UNSET)
+ self.orderState.suggestedSize = decode(Decimal, fields)
+ self.orderState.rejectReason = decode(str, fields)
+
+ accountsCount = decode(int, fields)
+ if accountsCount > 0:
+ self.orderState.orderAllocations = []
+ for _ in range(accountsCount):
+ orderAllocation = OrderAllocation()
+ orderAllocation.account = decode(str, fields)
+ orderAllocation.position = decode(Decimal, fields)
+ orderAllocation.positionDesired = decode(Decimal, fields)
+ orderAllocation.positionAfter = decode(Decimal, fields)
+ orderAllocation.desiredAllocQty = decode(Decimal, fields)
+ orderAllocation.allowedAllocQty = decode(Decimal, fields)
+ orderAllocation.isMonetary = decode(bool, fields)
+ self.orderState.orderAllocations.append(orderAllocation)
+ self.orderState.warningText = decode(str, fields)
+
+ def decodeVolRandomizeFlags(self, fields):
+ if self.version >= 34:
+ self.order.randomizeSize = decode(bool, fields)
+ self.order.randomizePrice = decode(bool, fields)
+
+ def decodePegToBenchParams(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK:
+ if isPegBenchOrder(self.order.orderType):
+ self.order.referenceContractId = decode(int, fields)
+ self.order.isPeggedChangeAmountDecrease = decode(bool, fields)
+ self.order.peggedChangeAmount = decode(float, fields)
+ self.order.referenceChangeAmount = decode(float, fields)
+ self.order.referenceExchangeId = decode(str, fields)
+
+ def decodeConditions(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK:
+ conditionsSize = decode(int, fields)
+ if conditionsSize > 0:
+ self.order.conditions = []
+ for _ in range(conditionsSize):
+ conditionType = decode(int, fields)
+ condition = order_condition.Create(conditionType)
+ condition.decode(fields)
+ self.order.conditions.append(condition)
+
+ self.order.conditionsIgnoreRth = decode(bool, fields)
+ self.order.conditionsCancelOrder = decode(bool, fields)
+
+ def decodeAdjustedOrderParams(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK:
+ self.order.adjustedOrderType = decode(str, fields)
+ self.order.triggerPrice = decode(float, fields)
+ OrderDecoder.decodeStopPriceAndLmtPriceOffset(self, fields)
+ self.order.adjustedStopPrice = decode(float, fields)
+ self.order.adjustedStopLimitPrice = decode(float, fields)
+ self.order.adjustedTrailingAmount = decode(float, fields)
+ self.order.adjustableTrailingUnit = decode(int, fields)
+
+ def decodeStopPriceAndLmtPriceOffset(self, fields):
+ self.order.trailStopPrice = decode(float, fields)
+ self.order.lmtPriceOffset = decode(float, fields)
+
+ def decodeSoftDollarTier(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_SOFT_DOLLAR_TIER:
+ name = decode(str, fields)
+ value = decode(str, fields)
+ displayName = decode(str, fields)
+ self.order.softDollarTier = SoftDollarTier(name, value, displayName)
+
+ def decodeCashQty(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_CASH_QTY:
+ self.order.cashQty = decode(float, fields)
+
+ def decodeDontUseAutoPriceForHedge(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE:
+ self.order.dontUseAutoPriceForHedge = decode(bool, fields)
+
+ def decodeIsOmsContainers(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_ORDER_CONTAINER:
+ self.order.isOmsContainer = decode(bool, fields)
+
+ def decodeDiscretionaryUpToLimitPrice(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_D_PEG_ORDERS:
+ self.order.discretionaryUpToLimitPrice = decode(bool, fields)
+
+ def decodeAutoCancelDate(self, fields):
+ self.order.autoCancelDate = decode(str, fields)
+
+ def decodeFilledQuantity(self, fields):
+ self.order.filledQuantity = decode(Decimal, fields)
+
+ def decodeRefFuturesConId(self, fields):
+ self.order.refFuturesConId = decode(int, fields)
+
+ def decodeAutoCancelParent(self, fields, minVersionAutoCancelParent=MIN_CLIENT_VER):
+ if self.serverVersion >= minVersionAutoCancelParent:
+ self.order.autoCancelParent = decode(bool, fields)
+
+ def decodeShareholder(self, fields):
+ self.order.shareholder = decode(str, fields)
+
+ def decodeImbalanceOnly(self, fields, minVersionImbalanceOnly=MIN_CLIENT_VER):
+ if self.serverVersion >= minVersionImbalanceOnly:
+ self.order.imbalanceOnly = decode(bool, fields)
+
+ def decodeRouteMarketableToBbo(self, fields):
+ self.order.routeMarketableToBbo = decode(bool, fields)
+
+ def decodeParentPermId(self, fields):
+ self.order.parentPermId = decode(int, fields)
+
+ def decodeCompletedTime(self, fields):
+ self.orderState.completedTime = decode(str, fields)
+
+ def decodeCompletedStatus(self, fields):
+ self.orderState.completedStatus = decode(str, fields)
+
+ def decodeUsePriceMgmtAlgo(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_PRICE_MGMT_ALGO:
+ self.order.usePriceMgmtAlgo = decode(bool, fields)
+
+ def decodeDuration(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_DURATION:
+ self.order.duration = decode(int, fields, SHOW_UNSET)
+
+ def decodePostToAts(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_POST_TO_ATS:
+ self.order.postToAts = decode(int, fields, SHOW_UNSET)
+
+ def decodePegBestPegMidOrderAttributes(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS:
+ self.order.minTradeQty = decode(int, fields, SHOW_UNSET)
+ self.order.minCompeteSize = decode(int, fields, SHOW_UNSET)
+ self.order.competeAgainstBestOffset = decode(float, fields, SHOW_UNSET)
+ self.order.midOffsetAtWhole = decode(float, fields, SHOW_UNSET)
+ self.order.midOffsetAtHalf = decode(float, fields, SHOW_UNSET)
+
+ def decodeCustomerAccount(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_CUSTOMER_ACCOUNT:
+ self.order.customerAccount = decode(str, fields)
+
+ def decodeProfessionalCustomer(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_PROFESSIONAL_CUSTOMER:
+ self.order.professionalCustomer = decode(bool, fields)
+
+ def decodeBondAccruedInterest(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_BOND_ACCRUED_INTEREST:
+ self.order.bondAccruedInterest = decode(str, fields)
+
+ def decodeIncludeOvernight(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_INCLUDE_OVERNIGHT:
+ self.order.includeOvernight = decode(bool, fields)
+
+ def decodeCMETaggingFields(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER:
+ self.order.extOperator = decode(str, fields)
+ self.order.manualOrderIndicator = decode(int, fields, SHOW_UNSET)
+
+ def decodeSubmitter(self, fields):
+ if self.serverVersion >= MIN_SERVER_VER_SUBMITTER:
+ self.order.submitter = decode(str, fields)
+
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountDataEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountDataEnd_pb2.py
new file mode 100644
index 00000000..25eb5dd4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountDataEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountDataEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountDataEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x41\x63\x63ountDataEnd.proto\x12\x08protobuf\":\n\x0e\x41\x63\x63ountDataEnd\x12\x18\n\x0b\x61\x63\x63ountName\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0e\n\x0c_accountNameB>\n\x16\x63om.ib.client.protobufB\x13\x41\x63\x63ountDataEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountDataEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023AccountDataEndProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTDATAEND']._serialized_start=34
+ _globals['_ACCOUNTDATAEND']._serialized_end=92
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountDataRequest_pb2.py
new file mode 100644
index 00000000..b0e46578
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountDataRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x41\x63\x63ountDataRequest.proto\x12\x08protobuf\"^\n\x12\x41\x63\x63ountDataRequest\x12\x16\n\tsubscribe\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x15\n\x08\x61\x63\x63tCode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0c\n\n_subscribeB\x0b\n\t_acctCodeBB\n\x16\x63om.ib.client.protobufB\x17\x41\x63\x63ountDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027AccountDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTDATAREQUEST']._serialized_start=38
+ _globals['_ACCOUNTDATAREQUEST']._serialized_end=132
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummaryEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummaryEnd_pb2.py
new file mode 100644
index 00000000..e32a0919
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummaryEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountSummaryEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountSummaryEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x41\x63\x63ountSummaryEnd.proto\x12\x08protobuf\"1\n\x11\x41\x63\x63ountSummaryEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBA\n\x16\x63om.ib.client.protobufB\x16\x41\x63\x63ountSummaryEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountSummaryEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026AccountSummaryEndProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTSUMMARYEND']._serialized_start=37
+ _globals['_ACCOUNTSUMMARYEND']._serialized_end=86
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummaryRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummaryRequest_pb2.py
new file mode 100644
index 00000000..7a3e9be5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummaryRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountSummaryRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountSummaryRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x41\x63\x63ountSummaryRequest.proto\x12\x08protobuf\"o\n\x15\x41\x63\x63ountSummaryRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05group\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x11\n\x04tags\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x08\n\x06_groupB\x07\n\x05_tagsBE\n\x16\x63om.ib.client.protobufB\x1a\x41\x63\x63ountSummaryRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountSummaryRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032AccountSummaryRequestProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTSUMMARYREQUEST']._serialized_start=41
+ _globals['_ACCOUNTSUMMARYREQUEST']._serialized_end=152
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummary_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummary_pb2.py
new file mode 100644
index 00000000..11417eec
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountSummary_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountSummary.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountSummary.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x41\x63\x63ountSummary.proto\x12\x08protobuf\"\xac\x01\n\x0e\x41\x63\x63ountSummary\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x10\n\x03tag\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x12\n\x05value\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08\x63urrency\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x06\n\x04_tagB\x08\n\x06_valueB\x0b\n\t_currencyB>\n\x16\x63om.ib.client.protobufB\x13\x41\x63\x63ountSummaryProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountSummary_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023AccountSummaryProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTSUMMARY']._serialized_start=35
+ _globals['_ACCOUNTSUMMARY']._serialized_end=207
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateMultiEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateMultiEnd_pb2.py
new file mode 100644
index 00000000..adc576ba
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateMultiEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountUpdateMultiEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountUpdateMultiEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x41\x63\x63ountUpdateMultiEnd.proto\x12\x08protobuf\"5\n\x15\x41\x63\x63ountUpdateMultiEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBE\n\x16\x63om.ib.client.protobufB\x1a\x41\x63\x63ountUpdateMultiEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountUpdateMultiEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032AccountUpdateMultiEndProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTUPDATEMULTIEND']._serialized_start=41
+ _globals['_ACCOUNTUPDATEMULTIEND']._serialized_end=94
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateMulti_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateMulti_pb2.py
new file mode 100644
index 00000000..54e93161
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateMulti_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountUpdateMulti.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountUpdateMulti.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x41\x63\x63ountUpdateMulti.proto\x12\x08protobuf\"\xd6\x01\n\x12\x41\x63\x63ountUpdateMulti\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodelCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x10\n\x03key\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x12\n\x05value\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08\x63urrency\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x0c\n\n_modelCodeB\x06\n\x04_keyB\x08\n\x06_valueB\x0b\n\t_currencyBB\n\x16\x63om.ib.client.protobufB\x17\x41\x63\x63ountUpdateMultiProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountUpdateMulti_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027AccountUpdateMultiProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTUPDATEMULTI']._serialized_start=39
+ _globals['_ACCOUNTUPDATEMULTI']._serialized_end=253
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateTime_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateTime_pb2.py
new file mode 100644
index 00000000..b5d4f8de
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdateTime_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountUpdateTime.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountUpdateTime.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x41\x63\x63ountUpdateTime.proto\x12\x08protobuf\"9\n\x11\x41\x63\x63ountUpdateTime\x12\x16\n\ttimeStamp\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0c\n\n_timeStampBA\n\x16\x63om.ib.client.protobufB\x16\x41\x63\x63ountUpdateTimeProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountUpdateTime_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026AccountUpdateTimeProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTUPDATETIME']._serialized_start=37
+ _globals['_ACCOUNTUPDATETIME']._serialized_end=94
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdatesMultiRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdatesMultiRequest_pb2.py
new file mode 100644
index 00000000..296abc57
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountUpdatesMultiRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountUpdatesMultiRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountUpdatesMultiRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n AccountUpdatesMultiRequest.proto\x12\x08protobuf\"\xae\x01\n\x1a\x41\x63\x63ountUpdatesMultiRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodelCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x19\n\x0cledgerAndNLV\x18\x04 \x01(\x08H\x03\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x0c\n\n_modelCodeB\x0f\n\r_ledgerAndNLVBJ\n\x16\x63om.ib.client.protobufB\x1f\x41\x63\x63ountUpdatesMultiRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountUpdatesMultiRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\037AccountUpdatesMultiRequestProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTUPDATESMULTIREQUEST']._serialized_start=47
+ _globals['_ACCOUNTUPDATESMULTIREQUEST']._serialized_end=221
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountValue_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountValue_pb2.py
new file mode 100644
index 00000000..765f2a27
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AccountValue_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AccountValue.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AccountValue.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x41\x63\x63ountValue.proto\x12\x08protobuf\"\x94\x01\n\x0c\x41\x63\x63ountValue\x12\x10\n\x03key\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x12\n\x05value\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x63urrency\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0b\x61\x63\x63ountName\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x06\n\x04_keyB\x08\n\x06_valueB\x0b\n\t_currencyB\x0e\n\x0c_accountNameB<\n\x16\x63om.ib.client.protobufB\x11\x41\x63\x63ountValueProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AccountValue_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021AccountValueProto\252\002\016IBApi.protobuf'
+ _globals['_ACCOUNTVALUE']._serialized_start=33
+ _globals['_ACCOUNTVALUE']._serialized_end=181
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AllOpenOrdersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AllOpenOrdersRequest_pb2.py
new file mode 100644
index 00000000..76dbf6aa
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AllOpenOrdersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AllOpenOrdersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AllOpenOrdersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x41llOpenOrdersRequest.proto\x12\x08protobuf\"\x16\n\x14\x41llOpenOrdersRequestBD\n\x16\x63om.ib.client.protobufB\x19\x41llOpenOrdersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AllOpenOrdersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031AllOpenOrdersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_ALLOPENORDERSREQUEST']._serialized_start=40
+ _globals['_ALLOPENORDERSREQUEST']._serialized_end=62
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiConfig_pb2.py
new file mode 100644
index 00000000..a3fd9bf5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiConfig_pb2.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ApiConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ApiConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.ApiPrecautionsConfig_pb2 as ApiPrecautionsConfig__pb2
+import ibapi.protobuf.ApiSettingsConfig_pb2 as ApiSettingsConfig__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x41piConfig.proto\x12\x08protobuf\x1a\x1a\x41piPrecautionsConfig.proto\x1a\x17\x41piSettingsConfig.proto\"\x96\x01\n\tApiConfig\x12\x38\n\x0bprecautions\x18\x01 \x01(\x0b\x32\x1e.protobuf.ApiPrecautionsConfigH\x00\x88\x01\x01\x12\x32\n\x08settings\x18\x02 \x01(\x0b\x32\x1b.protobuf.ApiSettingsConfigH\x01\x88\x01\x01\x42\x0e\n\x0c_precautionsB\x0b\n\t_settingsB9\n\x16\x63om.ib.client.protobufB\x0e\x41piConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ApiConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016ApiConfigProto\252\002\016IBApi.protobuf'
+ _globals['_APICONFIG']._serialized_start=83
+ _globals['_APICONFIG']._serialized_end=233
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiPrecautionsConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiPrecautionsConfig_pb2.py
new file mode 100644
index 00000000..6546da23
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiPrecautionsConfig_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ApiPrecautionsConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ApiPrecautionsConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x41piPrecautionsConfig.proto\x12\x08protobuf\"\xee\x05\n\x14\x41piPrecautionsConfig\x12#\n\x16\x62ypassOrderPrecautions\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1e\n\x11\x62ypassBondWarning\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12,\n\x1f\x62ypassNegativeYieldConfirmation\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12$\n\x17\x62ypassCalledBondWarning\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12-\n bypassSameActionPairTradeWarning\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12)\n\x1c\x62ypassFlaggedAccountsWarning\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12.\n!bypassPriceBasedVolatilityWarning\x18\x07 \x01(\x08H\x06\x88\x01\x01\x12\'\n\x1a\x62ypassRedirectOrderWarning\x18\x08 \x01(\x08H\x07\x88\x01\x01\x12\'\n\x1a\x62ypassNoOverfillProtection\x18\t \x01(\x08H\x08\x88\x01\x01\x12\'\n\x1a\x62ypassRouteMarketableToBBO\x18\n \x01(\x08H\t\x88\x01\x01\x42\x19\n\x17_bypassOrderPrecautionsB\x14\n\x12_bypassBondWarningB\"\n _bypassNegativeYieldConfirmationB\x1a\n\x18_bypassCalledBondWarningB#\n!_bypassSameActionPairTradeWarningB\x1f\n\x1d_bypassFlaggedAccountsWarningB$\n\"_bypassPriceBasedVolatilityWarningB\x1d\n\x1b_bypassRedirectOrderWarningB\x1d\n\x1b_bypassNoOverfillProtectionB\x1d\n\x1b_bypassRouteMarketableToBBOBD\n\x16\x63om.ib.client.protobufB\x19\x41piPrecautionsConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ApiPrecautionsConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031ApiPrecautionsConfigProto\252\002\016IBApi.protobuf'
+ _globals['_APIPRECAUTIONSCONFIG']._serialized_start=41
+ _globals['_APIPRECAUTIONSCONFIG']._serialized_end=791
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiSettingsConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiSettingsConfig_pb2.py
new file mode 100644
index 00000000..128bd6e1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ApiSettingsConfig_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ApiSettingsConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ApiSettingsConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x41piSettingsConfig.proto\x12\x08protobuf\"\xdf\x13\n\x11\x41piSettingsConfig\x12\x18\n\x0breadOnlyApi\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12(\n\x1btotalQuantityForMutualFunds\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12+\n\x1e\x64ownloadOpenOrdersOnConnection\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12&\n\x19includeVirtualFxPositions\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x1c\n\x0fprepareDailyPnL\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x31\n$sendStatusUpdatesForVolatilityOrders\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x1e\n\x11\x65ncodeApiMessages\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x17\n\nsocketPort\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12!\n\x14useNegativeAutoRange\x18\t \x01(\x08H\x08\x88\x01\x01\x12$\n\x17\x63reateApiMessageLogFile\x18\n \x01(\x08H\t\x88\x01\x01\x12\'\n\x1aincludeMarketDataInLogFile\x18\x0b \x01(\x08H\n\x88\x01\x01\x12\'\n\x1a\x65xposeTradingScheduleToApi\x18\x0c \x01(\x08H\x0b\x88\x01\x01\x12/\n\"splitInsuredDepositFromCashBalance\x18\r \x01(\x08H\x0c\x88\x01\x01\x12*\n\x1dsendZeroPositionsForTodayOnly\x18\x0e \x01(\x08H\r\x88\x01\x01\x12\x34\n\'letApiAccountRequestsSwitchSubscription\x18\x0f \x01(\x08H\x0e\x88\x01\x01\x12\x32\n%useAccountGroupsWithAllocationMethods\x18\x10 \x01(\x08H\x0f\x88\x01\x01\x12\x19\n\x0cloggingLevel\x18\x11 \x01(\tH\x10\x88\x01\x01\x12\x1b\n\x0emasterClientId\x18\x12 \x01(\x05H\x11\x88\x01\x01\x12\x1c\n\x0f\x62ulkDataTimeout\x18\x13 \x01(\x05H\x12\x88\x01\x01\x12#\n\x16\x63omponentExchSeparator\x18\x14 \x01(\tH\x13\x88\x01\x01\x12$\n\x17showForexDataIn1_10Pips\x18\x15 \x01(\x08H\x14\x88\x01\x01\x12(\n\x1b\x61llowForexTradingIn1_10Pips\x18\x16 \x01(\x08H\x15\x88\x01\x01\x12\x33\n&roundAccountValuesToNearestWholeNumber\x18\x17 \x01(\x08H\x16\x88\x01\x01\x12,\n\x1fsendMarketDataInLotsForUsStocks\x18\x18 \x01(\x08H\x17\x88\x01\x01\x12(\n\x1bshowAdvancedOrderRejectInUi\x18\x19 \x01(\x08H\x18\x88\x01\x01\x12\'\n\x1arejectMessagesAboveMaxRate\x18\x1a \x01(\x08H\x19\x88\x01\x01\x12\x30\n#maintainConnectionOnIncorrectFields\x18\x1b \x01(\x08H\x1a\x88\x01\x01\x12*\n\x1d\x63ompatibilityModeNasdaqStocks\x18\x1c \x01(\x08H\x1b\x88\x01\x01\x12#\n\x16sendInstrumentTimezone\x18\x1d \x01(\tH\x1c\x88\x01\x01\x12-\n sendForexDataInCompatibilityMode\x18\x1e \x01(\x08H\x1d\x88\x01\x01\x12\x31\n$maintainAndResubmitOrdersOnReconnect\x18\x1f \x01(\x08H\x1e\x88\x01\x01\x12\"\n\x15historicalDataMaxSize\x18 \x01(\x05H\x1f\x88\x01\x01\x12\x31\n$autoReportNettingEventContractTrades\x18! \x01(\x08H \x88\x01\x01\x12&\n\x19optionExerciseRequestType\x18\" \x01(\tH!\x88\x01\x01\x12\x1f\n\x12\x61llowLocalhostOnly\x18# \x01(\x08H\"\x88\x01\x01\x12\x12\n\ntrustedIPs\x18$ \x03(\tB\x0e\n\x0c_readOnlyApiB\x1e\n\x1c_totalQuantityForMutualFundsB!\n\x1f_downloadOpenOrdersOnConnectionB\x1c\n\x1a_includeVirtualFxPositionsB\x12\n\x10_prepareDailyPnLB\'\n%_sendStatusUpdatesForVolatilityOrdersB\x14\n\x12_encodeApiMessagesB\r\n\x0b_socketPortB\x17\n\x15_useNegativeAutoRangeB\x1a\n\x18_createApiMessageLogFileB\x1d\n\x1b_includeMarketDataInLogFileB\x1d\n\x1b_exposeTradingScheduleToApiB%\n#_splitInsuredDepositFromCashBalanceB \n\x1e_sendZeroPositionsForTodayOnlyB*\n(_letApiAccountRequestsSwitchSubscriptionB(\n&_useAccountGroupsWithAllocationMethodsB\x0f\n\r_loggingLevelB\x11\n\x0f_masterClientIdB\x12\n\x10_bulkDataTimeoutB\x19\n\x17_componentExchSeparatorB\x1a\n\x18_showForexDataIn1_10PipsB\x1e\n\x1c_allowForexTradingIn1_10PipsB)\n\'_roundAccountValuesToNearestWholeNumberB\"\n _sendMarketDataInLotsForUsStocksB\x1e\n\x1c_showAdvancedOrderRejectInUiB\x1d\n\x1b_rejectMessagesAboveMaxRateB&\n$_maintainConnectionOnIncorrectFieldsB \n\x1e_compatibilityModeNasdaqStocksB\x19\n\x17_sendInstrumentTimezoneB#\n!_sendForexDataInCompatibilityModeB\'\n%_maintainAndResubmitOrdersOnReconnectB\x18\n\x16_historicalDataMaxSizeB\'\n%_autoReportNettingEventContractTradesB\x1c\n\x1a_optionExerciseRequestTypeB\x15\n\x13_allowLocalhostOnlyBA\n\x16\x63om.ib.client.protobufB\x16\x41piSettingsConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ApiSettingsConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026ApiSettingsConfigProto\252\002\016IBApi.protobuf'
+ _globals['_APISETTINGSCONFIG']._serialized_start=38
+ _globals['_APISETTINGSCONFIG']._serialized_end=2565
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AttachedOrders_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AttachedOrders_pb2.py
new file mode 100644
index 00000000..adc92b5b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AttachedOrders_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AttachedOrders.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AttachedOrders.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x41ttachedOrders.proto\x12\x08protobuf\"\xb0\x01\n\x0e\x41ttachedOrders\x12\x16\n\tslOrderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x18\n\x0bslOrderType\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tptOrderId\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x18\n\x0bptOrderType\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x0c\n\n_slOrderIdB\x0e\n\x0c_slOrderTypeB\x0c\n\n_ptOrderIdB\x0e\n\x0c_ptOrderTypeB>\n\x16\x63om.ib.client.protobufB\x13\x41ttachedOrdersProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AttachedOrders_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023AttachedOrdersProto\252\002\016IBApi.protobuf'
+ _globals['_ATTACHEDORDERS']._serialized_start=35
+ _globals['_ATTACHEDORDERS']._serialized_end=211
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AutoOpenOrdersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AutoOpenOrdersRequest_pb2.py
new file mode 100644
index 00000000..5dbd99cc
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/AutoOpenOrdersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: AutoOpenOrdersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'AutoOpenOrdersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x41utoOpenOrdersRequest.proto\x12\x08protobuf\";\n\x15\x41utoOpenOrdersRequest\x12\x15\n\x08\x61utoBind\x18\x01 \x01(\x08H\x00\x88\x01\x01\x42\x0b\n\t_autoBindBE\n\x16\x63om.ib.client.protobufB\x1a\x41utoOpenOrdersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'AutoOpenOrdersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032AutoOpenOrdersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_AUTOOPENORDERSREQUEST']._serialized_start=41
+ _globals['_AUTOOPENORDERSREQUEST']._serialized_end=100
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CalculateImpliedVolatilityRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CalculateImpliedVolatilityRequest_pb2.py
new file mode 100644
index 00000000..fa63ef67
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CalculateImpliedVolatilityRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CalculateImpliedVolatilityRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CalculateImpliedVolatilityRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'CalculateImpliedVolatilityRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xf9\x02\n!CalculateImpliedVolatilityRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x18\n\x0boptionPrice\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x17\n\nunderPrice\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12k\n\x18impliedVolatilityOptions\x18\x05 \x03(\x0b\x32I.protobuf.CalculateImpliedVolatilityRequest.ImpliedVolatilityOptionsEntry\x1a?\n\x1dImpliedVolatilityOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x0e\n\x0c_optionPriceB\r\n\x0b_underPriceBQ\n\x16\x63om.ib.client.protobufB&CalculateImpliedVolatilityRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CalculateImpliedVolatilityRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB&CalculateImpliedVolatilityRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CALCULATEIMPLIEDVOLATILITYREQUEST_IMPLIEDVOLATILITYOPTIONSENTRY']._loaded_options = None
+ _globals['_CALCULATEIMPLIEDVOLATILITYREQUEST_IMPLIEDVOLATILITYOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_CALCULATEIMPLIEDVOLATILITYREQUEST']._serialized_start=70
+ _globals['_CALCULATEIMPLIEDVOLATILITYREQUEST']._serialized_end=447
+ _globals['_CALCULATEIMPLIEDVOLATILITYREQUEST_IMPLIEDVOLATILITYOPTIONSENTRY']._serialized_start=330
+ _globals['_CALCULATEIMPLIEDVOLATILITYREQUEST_IMPLIEDVOLATILITYOPTIONSENTRY']._serialized_end=393
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CalculateOptionPriceRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CalculateOptionPriceRequest_pb2.py
new file mode 100644
index 00000000..ab438dcc
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CalculateOptionPriceRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CalculateOptionPriceRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CalculateOptionPriceRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!CalculateOptionPriceRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xd9\x02\n\x1b\x43\x61lculateOptionPriceRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x17\n\nvolatility\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x17\n\nunderPrice\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12Y\n\x12optionPriceOptions\x18\x05 \x03(\x0b\x32=.protobuf.CalculateOptionPriceRequest.OptionPriceOptionsEntry\x1a\x39\n\x17OptionPriceOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\r\n\x0b_volatilityB\r\n\x0b_underPriceBK\n\x16\x63om.ib.client.protobufB CalculateOptionPriceRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CalculateOptionPriceRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB CalculateOptionPriceRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CALCULATEOPTIONPRICEREQUEST_OPTIONPRICEOPTIONSENTRY']._loaded_options = None
+ _globals['_CALCULATEOPTIONPRICEREQUEST_OPTIONPRICEOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_CALCULATEOPTIONPRICEREQUEST']._serialized_start=64
+ _globals['_CALCULATEOPTIONPRICEREQUEST']._serialized_end=409
+ _globals['_CALCULATEOPTIONPRICEREQUEST_OPTIONPRICEOPTIONSENTRY']._serialized_start=299
+ _globals['_CALCULATEOPTIONPRICEREQUEST_OPTIONPRICEOPTIONSENTRY']._serialized_end=356
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelAccountSummary_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelAccountSummary_pb2.py
new file mode 100644
index 00000000..28d75d5f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelAccountSummary_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelAccountSummary.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelAccountSummary.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x43\x61ncelAccountSummary.proto\x12\x08protobuf\"4\n\x14\x43\x61ncelAccountSummary\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBD\n\x16\x63om.ib.client.protobufB\x19\x43\x61ncelAccountSummaryProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelAccountSummary_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031CancelAccountSummaryProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELACCOUNTSUMMARY']._serialized_start=40
+ _globals['_CANCELACCOUNTSUMMARY']._serialized_end=92
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelAccountUpdatesMulti_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelAccountUpdatesMulti_pb2.py
new file mode 100644
index 00000000..1639e644
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelAccountUpdatesMulti_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelAccountUpdatesMulti.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelAccountUpdatesMulti.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x43\x61ncelAccountUpdatesMulti.proto\x12\x08protobuf\"9\n\x19\x43\x61ncelAccountUpdatesMulti\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBI\n\x16\x63om.ib.client.protobufB\x1e\x43\x61ncelAccountUpdatesMultiProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelAccountUpdatesMulti_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\036CancelAccountUpdatesMultiProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELACCOUNTUPDATESMULTI']._serialized_start=45
+ _globals['_CANCELACCOUNTUPDATESMULTI']._serialized_end=102
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelCalculateImpliedVolatility_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelCalculateImpliedVolatility_pb2.py
new file mode 100644
index 00000000..b77e2033
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelCalculateImpliedVolatility_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelCalculateImpliedVolatility.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelCalculateImpliedVolatility.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n&CancelCalculateImpliedVolatility.proto\x12\x08protobuf\"@\n CancelCalculateImpliedVolatility\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBP\n\x16\x63om.ib.client.protobufB%CancelCalculateImpliedVolatilityProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelCalculateImpliedVolatility_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB%CancelCalculateImpliedVolatilityProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELCALCULATEIMPLIEDVOLATILITY']._serialized_start=52
+ _globals['_CANCELCALCULATEIMPLIEDVOLATILITY']._serialized_end=116
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelCalculateOptionPrice_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelCalculateOptionPrice_pb2.py
new file mode 100644
index 00000000..fb6729ae
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelCalculateOptionPrice_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelCalculateOptionPrice.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelCalculateOptionPrice.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n CancelCalculateOptionPrice.proto\x12\x08protobuf\":\n\x1a\x43\x61ncelCalculateOptionPrice\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBJ\n\x16\x63om.ib.client.protobufB\x1f\x43\x61ncelCalculateOptionPriceProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelCalculateOptionPrice_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\037CancelCalculateOptionPriceProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELCALCULATEOPTIONPRICE']._serialized_start=46
+ _globals['_CANCELCALCULATEOPTIONPRICE']._serialized_end=104
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelContractData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelContractData_pb2.py
new file mode 100644
index 00000000..8e710978
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelContractData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelContractData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelContractData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x43\x61ncelContractData.proto\x12\x08protobuf\"2\n\x12\x43\x61ncelContractData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBB\n\x16\x63om.ib.client.protobufB\x17\x43\x61ncelContractDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelContractData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027CancelContractDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELCONTRACTDATA']._serialized_start=38
+ _globals['_CANCELCONTRACTDATA']._serialized_end=88
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelFundamentalsData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelFundamentalsData_pb2.py
new file mode 100644
index 00000000..9c3be524
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelFundamentalsData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelFundamentalsData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelFundamentalsData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x43\x61ncelFundamentalsData.proto\x12\x08protobuf\"6\n\x16\x43\x61ncelFundamentalsData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBF\n\x16\x63om.ib.client.protobufB\x1b\x43\x61ncelFundamentalsDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelFundamentalsData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033CancelFundamentalsDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELFUNDAMENTALSDATA']._serialized_start=42
+ _globals['_CANCELFUNDAMENTALSDATA']._serialized_end=96
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHeadTimestamp_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHeadTimestamp_pb2.py
new file mode 100644
index 00000000..4079bbfc
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHeadTimestamp_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelHeadTimestamp.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelHeadTimestamp.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x43\x61ncelHeadTimestamp.proto\x12\x08protobuf\"3\n\x13\x43\x61ncelHeadTimestamp\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBC\n\x16\x63om.ib.client.protobufB\x18\x43\x61ncelHeadTimestampProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelHeadTimestamp_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030CancelHeadTimestampProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELHEADTIMESTAMP']._serialized_start=39
+ _globals['_CANCELHEADTIMESTAMP']._serialized_end=90
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistogramData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistogramData_pb2.py
new file mode 100644
index 00000000..3169a29a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistogramData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelHistogramData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelHistogramData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x43\x61ncelHistogramData.proto\x12\x08protobuf\"3\n\x13\x43\x61ncelHistogramData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBC\n\x16\x63om.ib.client.protobufB\x18\x43\x61ncelHistogramDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelHistogramData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030CancelHistogramDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELHISTOGRAMDATA']._serialized_start=39
+ _globals['_CANCELHISTOGRAMDATA']._serialized_end=90
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistoricalData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistoricalData_pb2.py
new file mode 100644
index 00000000..8e9d1508
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistoricalData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelHistoricalData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelHistoricalData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x43\x61ncelHistoricalData.proto\x12\x08protobuf\"4\n\x14\x43\x61ncelHistoricalData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBD\n\x16\x63om.ib.client.protobufB\x19\x43\x61ncelHistoricalDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelHistoricalData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031CancelHistoricalDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELHISTORICALDATA']._serialized_start=40
+ _globals['_CANCELHISTORICALDATA']._serialized_end=92
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistoricalTicks_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistoricalTicks_pb2.py
new file mode 100644
index 00000000..d3998e1e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelHistoricalTicks_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelHistoricalTicks.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelHistoricalTicks.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1b\x43\x61ncelHistoricalTicks.proto\x12\x08protobuf\"5\n\x15\x43\x61ncelHistoricalTicks\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBE\n\x16\x63om.ib.client.protobufB\x1a\x43\x61ncelHistoricalTicksProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelHistoricalTicks_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032CancelHistoricalTicksProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELHISTORICALTICKS']._serialized_start=41
+ _globals['_CANCELHISTORICALTICKS']._serialized_end=94
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelMarketData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelMarketData_pb2.py
new file mode 100644
index 00000000..2e20e4aa
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelMarketData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelMarketData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelMarketData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x43\x61ncelMarketData.proto\x12\x08protobuf\"0\n\x10\x43\x61ncelMarketData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB@\n\x16\x63om.ib.client.protobufB\x15\x43\x61ncelMarketDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelMarketData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025CancelMarketDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELMARKETDATA']._serialized_start=36
+ _globals['_CANCELMARKETDATA']._serialized_end=84
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelMarketDepth_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelMarketDepth_pb2.py
new file mode 100644
index 00000000..fb7ef0d8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelMarketDepth_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelMarketDepth.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelMarketDepth.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x43\x61ncelMarketDepth.proto\x12\x08protobuf\"]\n\x11\x43\x61ncelMarketDepth\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x19\n\x0cisSmartDepth\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0f\n\r_isSmartDepthBA\n\x16\x63om.ib.client.protobufB\x16\x43\x61ncelMarketDepthProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelMarketDepth_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026CancelMarketDepthProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELMARKETDEPTH']._serialized_start=37
+ _globals['_CANCELMARKETDEPTH']._serialized_end=130
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelNewsBulletins_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelNewsBulletins_pb2.py
new file mode 100644
index 00000000..ca4c8725
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelNewsBulletins_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelNewsBulletins.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelNewsBulletins.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x43\x61ncelNewsBulletins.proto\x12\x08protobuf\"\x15\n\x13\x43\x61ncelNewsBulletinsBC\n\x16\x63om.ib.client.protobufB\x18\x43\x61ncelNewsBulletinsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelNewsBulletins_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030CancelNewsBulletinsProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELNEWSBULLETINS']._serialized_start=39
+ _globals['_CANCELNEWSBULLETINS']._serialized_end=60
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelOrderRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelOrderRequest_pb2.py
new file mode 100644
index 00000000..1641fb19
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelOrderRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelOrderRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelOrderRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.OrderCancel_pb2 as OrderCancel__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x43\x61ncelOrderRequest.proto\x12\x08protobuf\x1a\x11OrderCancel.proto\"w\n\x12\x43\x61ncelOrderRequest\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12/\n\x0borderCancel\x18\x02 \x01(\x0b\x32\x15.protobuf.OrderCancelH\x01\x88\x01\x01\x42\n\n\x08_orderIdB\x0e\n\x0c_orderCancelBB\n\x16\x63om.ib.client.protobufB\x17\x43\x61ncelOrderRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelOrderRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027CancelOrderRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELORDERREQUEST']._serialized_start=57
+ _globals['_CANCELORDERREQUEST']._serialized_end=176
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPnLSingle_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPnLSingle_pb2.py
new file mode 100644
index 00000000..97b63154
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPnLSingle_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelPnLSingle.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelPnLSingle.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x43\x61ncelPnLSingle.proto\x12\x08protobuf\"/\n\x0f\x43\x61ncelPnLSingle\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB?\n\x16\x63om.ib.client.protobufB\x14\x43\x61ncelPnLSingleProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelPnLSingle_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024CancelPnLSingleProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELPNLSINGLE']._serialized_start=35
+ _globals['_CANCELPNLSINGLE']._serialized_end=82
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPnL_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPnL_pb2.py
new file mode 100644
index 00000000..392299cb
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPnL_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelPnL.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelPnL.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x43\x61ncelPnL.proto\x12\x08protobuf\")\n\tCancelPnL\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB9\n\x16\x63om.ib.client.protobufB\x0e\x43\x61ncelPnLProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelPnL_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016CancelPnLProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELPNL']._serialized_start=29
+ _globals['_CANCELPNL']._serialized_end=70
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPositionsMulti_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPositionsMulti_pb2.py
new file mode 100644
index 00000000..1db51552
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPositionsMulti_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelPositionsMulti.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelPositionsMulti.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x43\x61ncelPositionsMulti.proto\x12\x08protobuf\"4\n\x14\x43\x61ncelPositionsMulti\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBD\n\x16\x63om.ib.client.protobufB\x19\x43\x61ncelPositionsMultiProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelPositionsMulti_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031CancelPositionsMultiProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELPOSITIONSMULTI']._serialized_start=40
+ _globals['_CANCELPOSITIONSMULTI']._serialized_end=92
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPositions_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPositions_pb2.py
new file mode 100644
index 00000000..abc0246c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelPositions_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelPositions.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelPositions.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x43\x61ncelPositions.proto\x12\x08protobuf\"\x11\n\x0f\x43\x61ncelPositionsB?\n\x16\x63om.ib.client.protobufB\x14\x43\x61ncelPositionsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelPositions_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024CancelPositionsProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELPOSITIONS']._serialized_start=35
+ _globals['_CANCELPOSITIONS']._serialized_end=52
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelRealTimeBars_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelRealTimeBars_pb2.py
new file mode 100644
index 00000000..4eb98131
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelRealTimeBars_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelRealTimeBars.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelRealTimeBars.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x43\x61ncelRealTimeBars.proto\x12\x08protobuf\"2\n\x12\x43\x61ncelRealTimeBars\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBB\n\x16\x63om.ib.client.protobufB\x17\x43\x61ncelRealTimeBarsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelRealTimeBars_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027CancelRealTimeBarsProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELREALTIMEBARS']._serialized_start=38
+ _globals['_CANCELREALTIMEBARS']._serialized_end=88
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelScannerSubscription_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelScannerSubscription_pb2.py
new file mode 100644
index 00000000..6bee619a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelScannerSubscription_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelScannerSubscription.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelScannerSubscription.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1f\x43\x61ncelScannerSubscription.proto\x12\x08protobuf\"9\n\x19\x43\x61ncelScannerSubscription\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBI\n\x16\x63om.ib.client.protobufB\x1e\x43\x61ncelScannerSubscriptionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelScannerSubscription_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\036CancelScannerSubscriptionProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELSCANNERSUBSCRIPTION']._serialized_start=45
+ _globals['_CANCELSCANNERSUBSCRIPTION']._serialized_end=102
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelTickByTick_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelTickByTick_pb2.py
new file mode 100644
index 00000000..c361bc5a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelTickByTick_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelTickByTick.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelTickByTick.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x43\x61ncelTickByTick.proto\x12\x08protobuf\"0\n\x10\x43\x61ncelTickByTick\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB@\n\x16\x63om.ib.client.protobufB\x15\x43\x61ncelTickByTickProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelTickByTick_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025CancelTickByTickProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELTICKBYTICK']._serialized_start=36
+ _globals['_CANCELTICKBYTICK']._serialized_end=84
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelWshEventData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelWshEventData_pb2.py
new file mode 100644
index 00000000..8961d2c1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelWshEventData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelWshEventData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelWshEventData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x43\x61ncelWshEventData.proto\x12\x08protobuf\"2\n\x12\x43\x61ncelWshEventData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBB\n\x16\x63om.ib.client.protobufB\x17\x43\x61ncelWshEventDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelWshEventData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027CancelWshEventDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELWSHEVENTDATA']._serialized_start=38
+ _globals['_CANCELWSHEVENTDATA']._serialized_end=88
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelWshMetaData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelWshMetaData_pb2.py
new file mode 100644
index 00000000..4e9d230f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CancelWshMetaData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CancelWshMetaData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CancelWshMetaData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17\x43\x61ncelWshMetaData.proto\x12\x08protobuf\"1\n\x11\x43\x61ncelWshMetaData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBA\n\x16\x63om.ib.client.protobufB\x16\x43\x61ncelWshMetaDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CancelWshMetaData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026CancelWshMetaDataProto\252\002\016IBApi.protobuf'
+ _globals['_CANCELWSHMETADATA']._serialized_start=37
+ _globals['_CANCELWSHMETADATA']._serialized_end=86
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ComboLeg_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ComboLeg_pb2.py
new file mode 100644
index 00000000..de98a85a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ComboLeg_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ComboLeg.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ComboLeg.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x43omboLeg.proto\x12\x08protobuf\"\xea\x02\n\x08\x43omboLeg\x12\x12\n\x05\x63onId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05ratio\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x61\x63tion\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x16\n\topenClose\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x1b\n\x0eshortSalesSlot\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x1f\n\x12\x64\x65signatedLocation\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x17\n\nexemptCode\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x18\n\x0bperLegPrice\x18\t \x01(\x01H\x08\x88\x01\x01\x42\x08\n\x06_conIdB\x08\n\x06_ratioB\t\n\x07_actionB\x0b\n\t_exchangeB\x0c\n\n_openCloseB\x11\n\x0f_shortSalesSlotB\x15\n\x13_designatedLocationB\r\n\x0b_exemptCodeB\x0e\n\x0c_perLegPriceB8\n\x16\x63om.ib.client.protobufB\rComboLegProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ComboLeg_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\rComboLegProto\252\002\016IBApi.protobuf'
+ _globals['_COMBOLEG']._serialized_start=29
+ _globals['_COMBOLEG']._serialized_end=391
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CommissionAndFeesReport_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CommissionAndFeesReport_pb2.py
new file mode 100644
index 00000000..b430c9fc
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CommissionAndFeesReport_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CommissionAndFeesReport.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CommissionAndFeesReport.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x43ommissionAndFeesReport.proto\x12\x08protobuf\"\x9d\x02\n\x17\x43ommissionAndFeesReport\x12\x13\n\x06\x65xecId\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1e\n\x11\x63ommissionAndFees\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x15\n\x08\x63urrency\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0brealizedPNL\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x16\n\tbondYield\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12 \n\x13yieldRedemptionDate\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\t\n\x07_execIdB\x14\n\x12_commissionAndFeesB\x0b\n\t_currencyB\x0e\n\x0c_realizedPNLB\x0c\n\n_bondYieldB\x16\n\x14_yieldRedemptionDateBG\n\x16\x63om.ib.client.protobufB\x1c\x43ommissionAndFeesReportProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CommissionAndFeesReport_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\034CommissionAndFeesReportProto\252\002\016IBApi.protobuf'
+ _globals['_COMMISSIONANDFEESREPORT']._serialized_start=44
+ _globals['_COMMISSIONANDFEESREPORT']._serialized_end=329
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrder_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrder_pb2.py
new file mode 100644
index 00000000..cc7515a6
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrder_pb2.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CompletedOrder.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CompletedOrder.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+import ibapi.protobuf.Order_pb2 as Order__pb2
+import ibapi.protobuf.OrderState_pb2 as OrderState__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x43ompletedOrder.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\x1a\x0bOrder.proto\x1a\x10OrderState.proto\"\xb5\x01\n\x0e\x43ompletedOrder\x12)\n\x08\x63ontract\x18\x01 \x01(\x0b\x32\x12.protobuf.ContractH\x00\x88\x01\x01\x12#\n\x05order\x18\x02 \x01(\x0b\x32\x0f.protobuf.OrderH\x01\x88\x01\x01\x12-\n\norderState\x18\x03 \x01(\x0b\x32\x14.protobuf.OrderStateH\x02\x88\x01\x01\x42\x0b\n\t_contractB\x08\n\x06_orderB\r\n\x0b_orderStateB>\n\x16\x63om.ib.client.protobufB\x13\x43ompletedOrderProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CompletedOrder_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023CompletedOrderProto\252\002\016IBApi.protobuf'
+ _globals['_COMPLETEDORDER']._serialized_start=82
+ _globals['_COMPLETEDORDER']._serialized_end=263
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrdersEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrdersEnd_pb2.py
new file mode 100644
index 00000000..e1a4c54b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrdersEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CompletedOrdersEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CompletedOrdersEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x43ompletedOrdersEnd.proto\x12\x08protobuf\"\x14\n\x12\x43ompletedOrdersEndBB\n\x16\x63om.ib.client.protobufB\x17\x43ompletedOrdersEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CompletedOrdersEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027CompletedOrdersEndProto\252\002\016IBApi.protobuf'
+ _globals['_COMPLETEDORDERSEND']._serialized_start=38
+ _globals['_COMPLETEDORDERSEND']._serialized_end=58
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrdersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrdersRequest_pb2.py
new file mode 100644
index 00000000..5f07f83a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CompletedOrdersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CompletedOrdersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CompletedOrdersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x43ompletedOrdersRequest.proto\x12\x08protobuf\":\n\x16\x43ompletedOrdersRequest\x12\x14\n\x07\x61piOnly\x18\x01 \x01(\x08H\x00\x88\x01\x01\x42\n\n\x08_apiOnlyBF\n\x16\x63om.ib.client.protobufB\x1b\x43ompletedOrdersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CompletedOrdersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033CompletedOrdersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_COMPLETEDORDERSREQUEST']._serialized_start=42
+ _globals['_COMPLETEDORDERSREQUEST']._serialized_end=100
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ConfigRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ConfigRequest_pb2.py
new file mode 100644
index 00000000..0fefc79a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ConfigRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ConfigRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ConfigRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13\x43onfigRequest.proto\x12\x08protobuf\"-\n\rConfigRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB=\n\x16\x63om.ib.client.protobufB\x12\x43onfigRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ConfigRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022ConfigRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CONFIGREQUEST']._serialized_start=33
+ _globals['_CONFIGREQUEST']._serialized_end=78
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ConfigResponse_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ConfigResponse_pb2.py
new file mode 100644
index 00000000..d23d6c1c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ConfigResponse_pb2.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ConfigResponse.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ConfigResponse.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.LockAndExitConfig_pb2 as LockAndExitConfig__pb2
+import ibapi.protobuf.MessageConfig_pb2 as MessageConfig__pb2
+import ibapi.protobuf.ApiConfig_pb2 as ApiConfig__pb2
+import ibapi.protobuf.OrdersConfig_pb2 as OrdersConfig__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x43onfigResponse.proto\x12\x08protobuf\x1a\x17LockAndExitConfig.proto\x1a\x13MessageConfig.proto\x1a\x0f\x41piConfig.proto\x1a\x12OrdersConfig.proto\"\x87\x02\n\x0e\x43onfigResponse\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x35\n\x0blockAndExit\x18\x02 \x01(\x0b\x32\x1b.protobuf.LockAndExitConfigH\x01\x88\x01\x01\x12)\n\x08messages\x18\x03 \x03(\x0b\x32\x17.protobuf.MessageConfig\x12%\n\x03\x61pi\x18\x04 \x01(\x0b\x32\x13.protobuf.ApiConfigH\x02\x88\x01\x01\x12+\n\x06orders\x18\x05 \x01(\x0b\x32\x16.protobuf.OrdersConfigH\x03\x88\x01\x01\x42\x08\n\x06_reqIdB\x0e\n\x0c_lockAndExitB\x06\n\x04_apiB\t\n\x07_ordersB>\n\x16\x63om.ib.client.protobufB\x13\x43onfigResponseProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ConfigResponse_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023ConfigResponseProto\252\002\016IBApi.protobuf'
+ _globals['_CONFIGRESPONSE']._serialized_start=118
+ _globals['_CONFIGRESPONSE']._serialized_end=381
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDataEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDataEnd_pb2.py
new file mode 100644
index 00000000..b42f8c96
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDataEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ContractDataEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ContractDataEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x43ontractDataEnd.proto\x12\x08protobuf\"/\n\x0f\x43ontractDataEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB?\n\x16\x63om.ib.client.protobufB\x14\x43ontractDataEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ContractDataEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024ContractDataEndProto\252\002\016IBApi.protobuf'
+ _globals['_CONTRACTDATAEND']._serialized_start=35
+ _globals['_CONTRACTDATAEND']._serialized_end=82
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDataRequest_pb2.py
new file mode 100644
index 00000000..868dbdad
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDataRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ContractDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ContractDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x43ontractDataRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"k\n\x13\x43ontractDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractBC\n\x16\x63om.ib.client.protobufB\x18\x43ontractDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ContractDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030ContractDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CONTRACTDATAREQUEST']._serialized_start=55
+ _globals['_CONTRACTDATAREQUEST']._serialized_end=162
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractData_pb2.py
new file mode 100644
index 00000000..fb38d7ad
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractData_pb2.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ContractData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ContractData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+import ibapi.protobuf.ContractDetails_pb2 as ContractDetails__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x43ontractData.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\x1a\x15\x43ontractDetails.proto\"\xb1\x01\n\x0c\x43ontractData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x37\n\x0f\x63ontractDetails\x18\x03 \x01(\x0b\x32\x19.protobuf.ContractDetailsH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x12\n\x10_contractDetailsB<\n\x16\x63om.ib.client.protobufB\x11\x43ontractDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ContractData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021ContractDataProto\252\002\016IBApi.protobuf'
+ _globals['_CONTRACTDATA']._serialized_start=72
+ _globals['_CONTRACTDATA']._serialized_end=249
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDescription_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDescription_pb2.py
new file mode 100644
index 00000000..d35354bd
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDescription_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ContractDescription.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ContractDescription.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x43ontractDescription.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"i\n\x13\x43ontractDescription\x12)\n\x08\x63ontract\x18\x01 \x01(\x0b\x32\x12.protobuf.ContractH\x00\x88\x01\x01\x12\x1a\n\x12\x64\x65rivativeSecTypes\x18\x02 \x03(\tB\x0b\n\t_contractBC\n\x16\x63om.ib.client.protobufB\x18\x43ontractDescriptionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ContractDescription_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030ContractDescriptionProto\252\002\016IBApi.protobuf'
+ _globals['_CONTRACTDESCRIPTION']._serialized_start=55
+ _globals['_CONTRACTDESCRIPTION']._serialized_end=160
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDetails_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDetails_pb2.py
new file mode 100644
index 00000000..5d2a5df5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ContractDetails_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ContractDetails.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ContractDetails.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.IneligibilityReason_pb2 as IneligibilityReason__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x43ontractDetails.proto\x12\x08protobuf\x1a\x19IneligibilityReason.proto\"\x8a\x18\n\x0f\x43ontractDetails\x12\x17\n\nmarketName\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07minTick\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x17\n\norderTypes\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1b\n\x0evalidExchanges\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1b\n\x0epriceMagnifier\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x17\n\nunderConId\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12\x15\n\x08longName\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1a\n\rcontractMonth\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x15\n\x08industry\x18\t \x01(\tH\x08\x88\x01\x01\x12\x15\n\x08\x63\x61tegory\x18\n \x01(\tH\t\x88\x01\x01\x12\x18\n\x0bsubcategory\x18\x0b \x01(\tH\n\x88\x01\x01\x12\x17\n\ntimeZoneId\x18\x0c \x01(\tH\x0b\x88\x01\x01\x12\x19\n\x0ctradingHours\x18\r \x01(\tH\x0c\x88\x01\x01\x12\x18\n\x0bliquidHours\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x13\n\x06\x65vRule\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x19\n\x0c\x65vMultiplier\x18\x10 \x01(\x01H\x0f\x88\x01\x01\x12;\n\tsecIdList\x18\x11 \x03(\x0b\x32(.protobuf.ContractDetails.SecIdListEntry\x12\x15\n\x08\x61ggGroup\x18\x12 \x01(\x05H\x10\x88\x01\x01\x12\x18\n\x0bunderSymbol\x18\x13 \x01(\tH\x11\x88\x01\x01\x12\x19\n\x0cunderSecType\x18\x14 \x01(\tH\x12\x88\x01\x01\x12\x1a\n\rmarketRuleIds\x18\x15 \x01(\tH\x13\x88\x01\x01\x12\x1f\n\x12realExpirationDate\x18\x16 \x01(\tH\x14\x88\x01\x01\x12\x16\n\tstockType\x18\x17 \x01(\tH\x15\x88\x01\x01\x12\x14\n\x07minSize\x18\x18 \x01(\tH\x16\x88\x01\x01\x12\x1a\n\rsizeIncrement\x18\x19 \x01(\tH\x17\x88\x01\x01\x12#\n\x16suggestedSizeIncrement\x18\x1a \x01(\tH\x18\x88\x01\x01\x12\x15\n\x08\x66undName\x18\x1b \x01(\tH\x19\x88\x01\x01\x12\x17\n\nfundFamily\x18\x1c \x01(\tH\x1a\x88\x01\x01\x12\x15\n\x08\x66undType\x18\x1d \x01(\tH\x1b\x88\x01\x01\x12\x1a\n\rfundFrontLoad\x18\x1e \x01(\tH\x1c\x88\x01\x01\x12\x19\n\x0c\x66undBackLoad\x18\x1f \x01(\tH\x1d\x88\x01\x01\x12%\n\x18\x66undBackLoadTimeInterval\x18 \x01(\tH\x1e\x88\x01\x01\x12\x1e\n\x11\x66undManagementFee\x18! \x01(\tH\x1f\x88\x01\x01\x12\x17\n\nfundClosed\x18\" \x01(\x08H \x88\x01\x01\x12&\n\x19\x66undClosedForNewInvestors\x18# \x01(\x08H!\x88\x01\x01\x12\"\n\x15\x66undClosedForNewMoney\x18$ \x01(\x08H\"\x88\x01\x01\x12\x1d\n\x10\x66undNotifyAmount\x18% \x01(\tH#\x88\x01\x01\x12\'\n\x1a\x66undMinimumInitialPurchase\x18& \x01(\tH$\x88\x01\x01\x12*\n\x1d\x66undMinimumSubsequentPurchase\x18\' \x01(\tH%\x88\x01\x01\x12\x1e\n\x11\x66undBlueSkyStates\x18( \x01(\tH&\x88\x01\x01\x12#\n\x16\x66undBlueSkyTerritories\x18) \x01(\tH\'\x88\x01\x01\x12,\n\x1f\x66undDistributionPolicyIndicator\x18* \x01(\tH(\x88\x01\x01\x12\x1a\n\rfundAssetType\x18+ \x01(\tH)\x88\x01\x01\x12\x12\n\x05\x63usip\x18, \x01(\tH*\x88\x01\x01\x12\x16\n\tissueDate\x18- \x01(\tH+\x88\x01\x01\x12\x14\n\x07ratings\x18. \x01(\tH,\x88\x01\x01\x12\x15\n\x08\x62ondType\x18/ \x01(\tH-\x88\x01\x01\x12\x13\n\x06\x63oupon\x18\x30 \x01(\x01H.\x88\x01\x01\x12\x17\n\ncouponType\x18\x31 \x01(\tH/\x88\x01\x01\x12\x18\n\x0b\x63onvertible\x18\x32 \x01(\x08H0\x88\x01\x01\x12\x15\n\x08\x63\x61llable\x18\x33 \x01(\x08H1\x88\x01\x01\x12\x15\n\x08puttable\x18\x34 \x01(\x08H2\x88\x01\x01\x12\x17\n\ndescAppend\x18\x35 \x01(\tH3\x88\x01\x01\x12\x1b\n\x0enextOptionDate\x18\x36 \x01(\tH4\x88\x01\x01\x12\x1b\n\x0enextOptionType\x18\x37 \x01(\tH5\x88\x01\x01\x12\x1e\n\x11nextOptionPartial\x18\x38 \x01(\x08H6\x88\x01\x01\x12\x16\n\tbondNotes\x18\x39 \x01(\tH7\x88\x01\x01\x12>\n\x17ineligibilityReasonList\x18: \x03(\x0b\x32\x1d.protobuf.IneligibilityReason\x12\x1b\n\x0e\x65ventContract1\x18; \x01(\tH8\x88\x01\x01\x12&\n\x19\x65ventContractDescription1\x18< \x01(\tH9\x88\x01\x01\x12&\n\x19\x65ventContractDescription2\x18= \x01(\tH:\x88\x01\x01\x12\x18\n\x0bminAlgoSize\x18> \x01(\tH;\x88\x01\x01\x12\x1f\n\x12lastPricePrecision\x18? \x01(\tH<\x88\x01\x01\x12\x1e\n\x11lastSizePrecision\x18@ \x01(\tH=\x88\x01\x01\x1a\x30\n\x0eSecIdListEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\r\n\x0b_marketNameB\n\n\x08_minTickB\r\n\x0b_orderTypesB\x11\n\x0f_validExchangesB\x11\n\x0f_priceMagnifierB\r\n\x0b_underConIdB\x0b\n\t_longNameB\x10\n\x0e_contractMonthB\x0b\n\t_industryB\x0b\n\t_categoryB\x0e\n\x0c_subcategoryB\r\n\x0b_timeZoneIdB\x0f\n\r_tradingHoursB\x0e\n\x0c_liquidHoursB\t\n\x07_evRuleB\x0f\n\r_evMultiplierB\x0b\n\t_aggGroupB\x0e\n\x0c_underSymbolB\x0f\n\r_underSecTypeB\x10\n\x0e_marketRuleIdsB\x15\n\x13_realExpirationDateB\x0c\n\n_stockTypeB\n\n\x08_minSizeB\x10\n\x0e_sizeIncrementB\x19\n\x17_suggestedSizeIncrementB\x0b\n\t_fundNameB\r\n\x0b_fundFamilyB\x0b\n\t_fundTypeB\x10\n\x0e_fundFrontLoadB\x0f\n\r_fundBackLoadB\x1b\n\x19_fundBackLoadTimeIntervalB\x14\n\x12_fundManagementFeeB\r\n\x0b_fundClosedB\x1c\n\x1a_fundClosedForNewInvestorsB\x18\n\x16_fundClosedForNewMoneyB\x13\n\x11_fundNotifyAmountB\x1d\n\x1b_fundMinimumInitialPurchaseB \n\x1e_fundMinimumSubsequentPurchaseB\x14\n\x12_fundBlueSkyStatesB\x19\n\x17_fundBlueSkyTerritoriesB\"\n _fundDistributionPolicyIndicatorB\x10\n\x0e_fundAssetTypeB\x08\n\x06_cusipB\x0c\n\n_issueDateB\n\n\x08_ratingsB\x0b\n\t_bondTypeB\t\n\x07_couponB\r\n\x0b_couponTypeB\x0e\n\x0c_convertibleB\x0b\n\t_callableB\x0b\n\t_puttableB\r\n\x0b_descAppendB\x11\n\x0f_nextOptionDateB\x11\n\x0f_nextOptionTypeB\x14\n\x12_nextOptionPartialB\x0c\n\n_bondNotesB\x11\n\x0f_eventContract1B\x1c\n\x1a_eventContractDescription1B\x1c\n\x1a_eventContractDescription2B\x0e\n\x0c_minAlgoSizeB\x15\n\x13_lastPricePrecisionB\x14\n\x12_lastSizePrecisionB?\n\x16\x63om.ib.client.protobufB\x14\x43ontractDetailsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ContractDetails_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024ContractDetailsProto\252\002\016IBApi.protobuf'
+ _globals['_CONTRACTDETAILS_SECIDLISTENTRY']._loaded_options = None
+ _globals['_CONTRACTDETAILS_SECIDLISTENTRY']._serialized_options = b'8\001'
+ _globals['_CONTRACTDETAILS']._serialized_start=63
+ _globals['_CONTRACTDETAILS']._serialized_end=3145
+ _globals['_CONTRACTDETAILS_SECIDLISTENTRY']._serialized_start=1962
+ _globals['_CONTRACTDETAILS_SECIDLISTENTRY']._serialized_end=2010
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Contract_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Contract_pb2.py
new file mode 100644
index 00000000..1a3bb450
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Contract_pb2.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: Contract.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'Contract.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.ComboLeg_pb2 as ComboLeg__pb2
+import ibapi.protobuf.DeltaNeutralContract_pb2 as DeltaNeutralContract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x43ontract.proto\x12\x08protobuf\x1a\x0e\x43omboLeg.proto\x1a\x1a\x44\x65ltaNeutralContract.proto\"\x8b\x07\n\x08\x43ontract\x12\x12\n\x05\x63onId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x13\n\x06symbol\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07secType\x18\x03 \x01(\tH\x02\x88\x01\x01\x12)\n\x1clastTradeDateOrContractMonth\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06strike\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x12\n\x05right\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x17\n\nmultiplier\x18\x07 \x01(\x01H\x06\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x18\n\x0bprimaryExch\x18\t \x01(\tH\x08\x88\x01\x01\x12\x15\n\x08\x63urrency\x18\n \x01(\tH\t\x88\x01\x01\x12\x18\n\x0blocalSymbol\x18\x0b \x01(\tH\n\x88\x01\x01\x12\x19\n\x0ctradingClass\x18\x0c \x01(\tH\x0b\x88\x01\x01\x12\x16\n\tsecIdType\x18\r \x01(\tH\x0c\x88\x01\x01\x12\x12\n\x05secId\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x15\n\x08issuerId\x18\x10 \x01(\tH\x0f\x88\x01\x01\x12\x41\n\x14\x64\x65ltaNeutralContract\x18\x11 \x01(\x0b\x32\x1e.protobuf.DeltaNeutralContractH\x10\x88\x01\x01\x12\x1b\n\x0eincludeExpired\x18\x12 \x01(\x08H\x11\x88\x01\x01\x12\x1d\n\x10\x63omboLegsDescrip\x18\x13 \x01(\tH\x12\x88\x01\x01\x12%\n\tcomboLegs\x18\x14 \x03(\x0b\x32\x12.protobuf.ComboLeg\x12\x1a\n\rlastTradeDate\x18\x15 \x01(\tH\x13\x88\x01\x01\x42\x08\n\x06_conIdB\t\n\x07_symbolB\n\n\x08_secTypeB\x1f\n\x1d_lastTradeDateOrContractMonthB\t\n\x07_strikeB\x08\n\x06_rightB\r\n\x0b_multiplierB\x0b\n\t_exchangeB\x0e\n\x0c_primaryExchB\x0b\n\t_currencyB\x0e\n\x0c_localSymbolB\x0f\n\r_tradingClassB\x0c\n\n_secIdTypeB\x08\n\x06_secIdB\x0e\n\x0c_descriptionB\x0b\n\t_issuerIdB\x17\n\x15_deltaNeutralContractB\x11\n\x0f_includeExpiredB\x13\n\x11_comboLegsDescripB\x10\n\x0e_lastTradeDateB8\n\x16\x63om.ib.client.protobufB\rContractProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'Contract_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\rContractProto\252\002\016IBApi.protobuf'
+ _globals['_CONTRACT']._serialized_start=73
+ _globals['_CONTRACT']._serialized_end=980
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeInMillisRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeInMillisRequest_pb2.py
new file mode 100644
index 00000000..b7ffe0ea
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeInMillisRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CurrentTimeInMillisRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CurrentTimeInMillisRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n CurrentTimeInMillisRequest.proto\x12\x08protobuf\"\x1c\n\x1a\x43urrentTimeInMillisRequestBJ\n\x16\x63om.ib.client.protobufB\x1f\x43urrentTimeInMillisRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CurrentTimeInMillisRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\037CurrentTimeInMillisRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CURRENTTIMEINMILLISREQUEST']._serialized_start=46
+ _globals['_CURRENTTIMEINMILLISREQUEST']._serialized_end=74
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeInMillis_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeInMillis_pb2.py
new file mode 100644
index 00000000..c79f9269
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeInMillis_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CurrentTimeInMillis.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CurrentTimeInMillis.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x43urrentTimeInMillis.proto\x12\x08protobuf\"O\n\x13\x43urrentTimeInMillis\x12 \n\x13\x63urrentTimeInMillis\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x16\n\x14_currentTimeInMillisBC\n\x16\x63om.ib.client.protobufB\x18\x43urrentTimeInMillisProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CurrentTimeInMillis_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030CurrentTimeInMillisProto\252\002\016IBApi.protobuf'
+ _globals['_CURRENTTIMEINMILLIS']._serialized_start=39
+ _globals['_CURRENTTIMEINMILLIS']._serialized_end=118
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeRequest_pb2.py
new file mode 100644
index 00000000..e286200c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTimeRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CurrentTimeRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CurrentTimeRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x43urrentTimeRequest.proto\x12\x08protobuf\"\x14\n\x12\x43urrentTimeRequestBB\n\x16\x63om.ib.client.protobufB\x17\x43urrentTimeRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CurrentTimeRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027CurrentTimeRequestProto\252\002\016IBApi.protobuf'
+ _globals['_CURRENTTIMEREQUEST']._serialized_start=38
+ _globals['_CURRENTTIMEREQUEST']._serialized_end=58
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTime_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTime_pb2.py
new file mode 100644
index 00000000..3d189388
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/CurrentTime_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: CurrentTime.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'CurrentTime.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x43urrentTime.proto\x12\x08protobuf\"7\n\x0b\x43urrentTime\x12\x18\n\x0b\x63urrentTime\x18\x01 \x01(\x03H\x00\x88\x01\x01\x42\x0e\n\x0c_currentTimeB;\n\x16\x63om.ib.client.protobufB\x10\x43urrentTimeProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'CurrentTime_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020CurrentTimeProto\252\002\016IBApi.protobuf'
+ _globals['_CURRENTTIME']._serialized_start=31
+ _globals['_CURRENTTIME']._serialized_end=86
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DeltaNeutralContract_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DeltaNeutralContract_pb2.py
new file mode 100644
index 00000000..5955ecfe
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DeltaNeutralContract_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: DeltaNeutralContract.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'DeltaNeutralContract.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1a\x44\x65ltaNeutralContract.proto\x12\x08protobuf\"p\n\x14\x44\x65ltaNeutralContract\x12\x12\n\x05\x63onId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05\x64\x65lta\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x12\n\x05price\x18\x03 \x01(\x01H\x02\x88\x01\x01\x42\x08\n\x06_conIdB\x08\n\x06_deltaB\x08\n\x06_priceBD\n\x16\x63om.ib.client.protobufB\x19\x44\x65ltaNeutralContractProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'DeltaNeutralContract_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031DeltaNeutralContractProto\252\002\016IBApi.protobuf'
+ _globals['_DELTANEUTRALCONTRACT']._serialized_start=40
+ _globals['_DELTANEUTRALCONTRACT']._serialized_end=152
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DepthMarketDataDescription_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DepthMarketDataDescription_pb2.py
new file mode 100644
index 00000000..319bbb57
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DepthMarketDataDescription_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: DepthMarketDataDescription.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'DepthMarketDataDescription.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n DepthMarketDataDescription.proto\x12\x08protobuf\"\xe2\x01\n\x1a\x44\x65pthMarketDataDescription\x12\x15\n\x08\x65xchange\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x14\n\x07secType\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0blistingExch\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1c\n\x0fserviceDataType\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08\x61ggGroup\x18\x05 \x01(\x05H\x04\x88\x01\x01\x42\x0b\n\t_exchangeB\n\n\x08_secTypeB\x0e\n\x0c_listingExchB\x12\n\x10_serviceDataTypeB\x0b\n\t_aggGroupBJ\n\x16\x63om.ib.client.protobufB\x1f\x44\x65pthMarketDataDescriptionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'DepthMarketDataDescription_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\037DepthMarketDataDescriptionProto\252\002\016IBApi.protobuf'
+ _globals['_DEPTHMARKETDATADESCRIPTION']._serialized_start=47
+ _globals['_DEPTHMARKETDATADESCRIPTION']._serialized_end=273
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DisplayGroupList_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DisplayGroupList_pb2.py
new file mode 100644
index 00000000..bdea7362
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DisplayGroupList_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: DisplayGroupList.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'DisplayGroupList.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x44isplayGroupList.proto\x12\x08protobuf\"P\n\x10\x44isplayGroupList\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x13\n\x06groups\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\t\n\x07_groupsB@\n\x16\x63om.ib.client.protobufB\x15\x44isplayGroupListProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'DisplayGroupList_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025DisplayGroupListProto\252\002\016IBApi.protobuf'
+ _globals['_DISPLAYGROUPLIST']._serialized_start=36
+ _globals['_DISPLAYGROUPLIST']._serialized_end=116
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DisplayGroupUpdated_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DisplayGroupUpdated_pb2.py
new file mode 100644
index 00000000..2c70e51d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/DisplayGroupUpdated_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: DisplayGroupUpdated.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'DisplayGroupUpdated.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x44isplayGroupUpdated.proto\x12\x08protobuf\"_\n\x13\x44isplayGroupUpdated\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x19\n\x0c\x63ontractInfo\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0f\n\r_contractInfoBC\n\x16\x63om.ib.client.protobufB\x18\x44isplayGroupUpdatedProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'DisplayGroupUpdated_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030DisplayGroupUpdatedProto\252\002\016IBApi.protobuf'
+ _globals['_DISPLAYGROUPUPDATED']._serialized_start=39
+ _globals['_DISPLAYGROUPUPDATED']._serialized_end=134
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ErrorMessage_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ErrorMessage_pb2.py
new file mode 100644
index 00000000..5fac78c4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ErrorMessage_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ErrorMessage.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ErrorMessage.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x45rrorMessage.proto\x12\x08protobuf\"\xd8\x01\n\x0c\x45rrorMessage\x12\x0f\n\x02id\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\terrorTime\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x16\n\terrorCode\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x15\n\x08\x65rrorMsg\x18\x04 \x01(\tH\x03\x88\x01\x01\x12$\n\x17\x61\x64vancedOrderRejectJson\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\x05\n\x03_idB\x0c\n\n_errorTimeB\x0c\n\n_errorCodeB\x0b\n\t_errorMsgB\x1a\n\x18_advancedOrderRejectJsonB<\n\x16\x63om.ib.client.protobufB\x11\x45rrorMessageProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ErrorMessage_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021ErrorMessageProto\252\002\016IBApi.protobuf'
+ _globals['_ERRORMESSAGE']._serialized_start=33
+ _globals['_ERRORMESSAGE']._serialized_end=249
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionDetailsEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionDetailsEnd_pb2.py
new file mode 100644
index 00000000..20e04dcc
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionDetailsEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ExecutionDetailsEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ExecutionDetailsEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19\x45xecutionDetailsEnd.proto\x12\x08protobuf\"3\n\x13\x45xecutionDetailsEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBC\n\x16\x63om.ib.client.protobufB\x18\x45xecutionDetailsEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ExecutionDetailsEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030ExecutionDetailsEndProto\252\002\016IBApi.protobuf'
+ _globals['_EXECUTIONDETAILSEND']._serialized_start=39
+ _globals['_EXECUTIONDETAILSEND']._serialized_end=90
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionDetails_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionDetails_pb2.py
new file mode 100644
index 00000000..d2637587
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionDetails_pb2.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ExecutionDetails.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ExecutionDetails.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+import ibapi.protobuf.Execution_pb2 as Execution__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x45xecutionDetails.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\x1a\x0f\x45xecution.proto\"\xa3\x01\n\x10\x45xecutionDetails\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12+\n\texecution\x18\x03 \x01(\x0b\x32\x13.protobuf.ExecutionH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x0c\n\n_executionB@\n\x16\x63om.ib.client.protobufB\x15\x45xecutionDetailsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ExecutionDetails_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025ExecutionDetailsProto\252\002\016IBApi.protobuf'
+ _globals['_EXECUTIONDETAILS']._serialized_start=70
+ _globals['_EXECUTIONDETAILS']._serialized_end=233
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionFilter_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionFilter_pb2.py
new file mode 100644
index 00000000..8d5d79d3
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionFilter_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ExecutionFilter.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ExecutionFilter.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15\x45xecutionFilter.proto\x12\x08protobuf\"\xb4\x02\n\x0f\x45xecutionFilter\x12\x15\n\x08\x63lientId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x61\x63\x63tCode\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x11\n\x04time\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x13\n\x06symbol\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x14\n\x07secType\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x11\n\x04side\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x16\n\tlastNDays\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x15\n\rspecificDates\x18\t \x03(\x05\x42\x0b\n\t_clientIdB\x0b\n\t_acctCodeB\x07\n\x05_timeB\t\n\x07_symbolB\n\n\x08_secTypeB\x0b\n\t_exchangeB\x07\n\x05_sideB\x0c\n\n_lastNDaysB?\n\x16\x63om.ib.client.protobufB\x14\x45xecutionFilterProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ExecutionFilter_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024ExecutionFilterProto\252\002\016IBApi.protobuf'
+ _globals['_EXECUTIONFILTER']._serialized_start=36
+ _globals['_EXECUTIONFILTER']._serialized_end=344
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionRequest_pb2.py
new file mode 100644
index 00000000..99ddbd4b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExecutionRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ExecutionRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ExecutionRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.ExecutionFilter_pb2 as ExecutionFilter__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x45xecutionRequest.proto\x12\x08protobuf\x1a\x15\x45xecutionFilter.proto\"}\n\x10\x45xecutionRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x37\n\x0f\x65xecutionFilter\x18\x02 \x01(\x0b\x32\x19.protobuf.ExecutionFilterH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x12\n\x10_executionFilterB@\n\x16\x63om.ib.client.protobufB\x15\x45xecutionRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ExecutionRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025ExecutionRequestProto\252\002\016IBApi.protobuf'
+ _globals['_EXECUTIONREQUEST']._serialized_start=59
+ _globals['_EXECUTIONREQUEST']._serialized_end=184
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Execution_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Execution_pb2.py
new file mode 100644
index 00000000..2c53b4a4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Execution_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: Execution.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'Execution.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x45xecution.proto\x12\x08protobuf\"\xaf\x06\n\tExecution\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x13\n\x06\x65xecId\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x11\n\x04time\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x17\n\nacctNumber\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x11\n\x04side\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x13\n\x06shares\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x12\n\x05price\x18\x08 \x01(\x01H\x07\x88\x01\x01\x12\x13\n\x06permId\x18\t \x01(\x03H\x08\x88\x01\x01\x12\x15\n\x08\x63lientId\x18\n \x01(\x05H\t\x88\x01\x01\x12\x1a\n\risLiquidation\x18\x0b \x01(\x08H\n\x88\x01\x01\x12\x13\n\x06\x63umQty\x18\x0c \x01(\tH\x0b\x88\x01\x01\x12\x15\n\x08\x61vgPrice\x18\r \x01(\x01H\x0c\x88\x01\x01\x12\x15\n\x08orderRef\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x13\n\x06\x65vRule\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x19\n\x0c\x65vMultiplier\x18\x10 \x01(\x01H\x0f\x88\x01\x01\x12\x16\n\tmodelCode\x18\x11 \x01(\tH\x10\x88\x01\x01\x12\x1a\n\rlastLiquidity\x18\x12 \x01(\x05H\x11\x88\x01\x01\x12#\n\x16isPriceRevisionPending\x18\x13 \x01(\x08H\x12\x88\x01\x01\x12\x16\n\tsubmitter\x18\x14 \x01(\tH\x13\x88\x01\x01\x12#\n\x16optExerciseOrLapseType\x18\x15 \x01(\x05H\x14\x88\x01\x01\x42\n\n\x08_orderIdB\t\n\x07_execIdB\x07\n\x05_timeB\r\n\x0b_acctNumberB\x0b\n\t_exchangeB\x07\n\x05_sideB\t\n\x07_sharesB\x08\n\x06_priceB\t\n\x07_permIdB\x0b\n\t_clientIdB\x10\n\x0e_isLiquidationB\t\n\x07_cumQtyB\x0b\n\t_avgPriceB\x0b\n\t_orderRefB\t\n\x07_evRuleB\x0f\n\r_evMultiplierB\x0c\n\n_modelCodeB\x10\n\x0e_lastLiquidityB\x19\n\x17_isPriceRevisionPendingB\x0c\n\n_submitterB\x19\n\x17_optExerciseOrLapseTypeB9\n\x16\x63om.ib.client.protobufB\x0e\x45xecutionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'Execution_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016ExecutionProto\252\002\016IBApi.protobuf'
+ _globals['_EXECUTION']._serialized_start=30
+ _globals['_EXECUTION']._serialized_end=845
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExerciseOptionsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExerciseOptionsRequest_pb2.py
new file mode 100644
index 00000000..43a41c5b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ExerciseOptionsRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ExerciseOptionsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ExerciseOptionsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1c\x45xerciseOptionsRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xbc\x03\n\x16\x45xerciseOptionsRequest\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x1b\n\x0e\x65xerciseAction\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x1d\n\x10\x65xerciseQuantity\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x15\n\x08override\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x1c\n\x0fmanualOrderTime\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x1c\n\x0f\x63ustomerAccount\x18\x08 \x01(\tH\x07\x88\x01\x01\x12!\n\x14professionalCustomer\x18\t \x01(\x08H\x08\x88\x01\x01\x42\n\n\x08_orderIdB\x0b\n\t_contractB\x11\n\x0f_exerciseActionB\x13\n\x11_exerciseQuantityB\n\n\x08_accountB\x0b\n\t_overrideB\x12\n\x10_manualOrderTimeB\x12\n\x10_customerAccountB\x17\n\x15_professionalCustomerBF\n\x16\x63om.ib.client.protobufB\x1b\x45xerciseOptionsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ExerciseOptionsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033ExerciseOptionsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_EXERCISEOPTIONSREQUEST']._serialized_start=59
+ _globals['_EXERCISEOPTIONSREQUEST']._serialized_end=503
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FAReplace_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FAReplace_pb2.py
new file mode 100644
index 00000000..4a6f4cba
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FAReplace_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FAReplace.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FAReplace.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x46\x41Replace.proto\x12\x08protobuf\"k\n\tFAReplace\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x17\n\nfaDataType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x10\n\x03xml\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\r\n\x0b_faDataTypeB\x06\n\x04_xmlB9\n\x16\x63om.ib.client.protobufB\x0e\x46\x41ReplaceProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FAReplace_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016FAReplaceProto\252\002\016IBApi.protobuf'
+ _globals['_FAREPLACE']._serialized_start=29
+ _globals['_FAREPLACE']._serialized_end=136
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FARequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FARequest_pb2.py
new file mode 100644
index 00000000..a46a76f3
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FARequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FARequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FARequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0f\x46\x41Request.proto\x12\x08protobuf\"3\n\tFARequest\x12\x17\n\nfaDataType\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\r\n\x0b_faDataTypeB9\n\x16\x63om.ib.client.protobufB\x0e\x46\x41RequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FARequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016FARequestProto\252\002\016IBApi.protobuf'
+ _globals['_FAREQUEST']._serialized_start=29
+ _globals['_FAREQUEST']._serialized_end=80
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCode_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCode_pb2.py
new file mode 100644
index 00000000..cf73444c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCode_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FamilyCode.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FamilyCode.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10\x46\x61milyCode.proto\x12\x08protobuf\"Z\n\nFamilyCode\x12\x16\n\taccountId\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\nfamilyCode\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0c\n\n_accountIdB\r\n\x0b_familyCodeB:\n\x16\x63om.ib.client.protobufB\x0f\x46\x61milyCodeProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FamilyCode_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017FamilyCodeProto\252\002\016IBApi.protobuf'
+ _globals['_FAMILYCODE']._serialized_start=30
+ _globals['_FAMILYCODE']._serialized_end=120
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCodesRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCodesRequest_pb2.py
new file mode 100644
index 00000000..36aa1656
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCodesRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FamilyCodesRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FamilyCodesRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18\x46\x61milyCodesRequest.proto\x12\x08protobuf\"\x14\n\x12\x46\x61milyCodesRequestBB\n\x16\x63om.ib.client.protobufB\x17\x46\x61milyCodesRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FamilyCodesRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027FamilyCodesRequestProto\252\002\016IBApi.protobuf'
+ _globals['_FAMILYCODESREQUEST']._serialized_start=38
+ _globals['_FAMILYCODESREQUEST']._serialized_end=58
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCodes_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCodes_pb2.py
new file mode 100644
index 00000000..4cb61071
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FamilyCodes_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FamilyCodes.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FamilyCodes.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.FamilyCode_pb2 as FamilyCode__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11\x46\x61milyCodes.proto\x12\x08protobuf\x1a\x10\x46\x61milyCode.proto\"8\n\x0b\x46\x61milyCodes\x12)\n\x0b\x66\x61milyCodes\x18\x01 \x03(\x0b\x32\x14.protobuf.FamilyCodeB;\n\x16\x63om.ib.client.protobufB\x10\x46\x61milyCodesProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FamilyCodes_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020FamilyCodesProto\252\002\016IBApi.protobuf'
+ _globals['_FAMILYCODES']._serialized_start=49
+ _globals['_FAMILYCODES']._serialized_end=105
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FundamentalsDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FundamentalsDataRequest_pb2.py
new file mode 100644
index 00000000..377b1f40
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FundamentalsDataRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FundamentalsDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FundamentalsDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1d\x46undamentalsDataRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xb8\x02\n\x17\x46undamentalsDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x17\n\nreportType\x18\x03 \x01(\tH\x02\x88\x01\x01\x12_\n\x17\x66undamentalsDataOptions\x18\x04 \x03(\x0b\x32>.protobuf.FundamentalsDataRequest.FundamentalsDataOptionsEntry\x1a>\n\x1c\x46undamentalsDataOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\r\n\x0b_reportTypeBG\n\x16\x63om.ib.client.protobufB\x1c\x46undamentalsDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FundamentalsDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\034FundamentalsDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_FUNDAMENTALSDATAREQUEST_FUNDAMENTALSDATAOPTIONSENTRY']._loaded_options = None
+ _globals['_FUNDAMENTALSDATAREQUEST_FUNDAMENTALSDATAOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_FUNDAMENTALSDATAREQUEST']._serialized_start=60
+ _globals['_FUNDAMENTALSDATAREQUEST']._serialized_end=372
+ _globals['_FUNDAMENTALSDATAREQUEST_FUNDAMENTALSDATAOPTIONSENTRY']._serialized_start=272
+ _globals['_FUNDAMENTALSDATAREQUEST_FUNDAMENTALSDATAOPTIONSENTRY']._serialized_end=334
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FundamentalsData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FundamentalsData_pb2.py
new file mode 100644
index 00000000..4571fd93
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/FundamentalsData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: FundamentalsData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'FundamentalsData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16\x46undamentalsData.proto\x12\x08protobuf\"L\n\x10\x46undamentalsData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x11\n\x04\x64\x61ta\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x07\n\x05_dataB@\n\x16\x63om.ib.client.protobufB\x15\x46undamentalsDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'FundamentalsData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025FundamentalsDataProto\252\002\016IBApi.protobuf'
+ _globals['_FUNDAMENTALSDATA']._serialized_start=36
+ _globals['_FUNDAMENTALSDATA']._serialized_end=112
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/GlobalCancelRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/GlobalCancelRequest_pb2.py
new file mode 100644
index 00000000..8aef0266
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/GlobalCancelRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: GlobalCancelRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'GlobalCancelRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.OrderCancel_pb2 as OrderCancel__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19GlobalCancelRequest.proto\x12\x08protobuf\x1a\x11OrderCancel.proto\"V\n\x13GlobalCancelRequest\x12/\n\x0borderCancel\x18\x01 \x01(\x0b\x32\x15.protobuf.OrderCancelH\x00\x88\x01\x01\x42\x0e\n\x0c_orderCancelBC\n\x16\x63om.ib.client.protobufB\x18GlobalCancelRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'GlobalCancelRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030GlobalCancelRequestProto\252\002\016IBApi.protobuf'
+ _globals['_GLOBALCANCELREQUEST']._serialized_start=58
+ _globals['_GLOBALCANCELREQUEST']._serialized_end=144
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HeadTimestampRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HeadTimestampRequest_pb2.py
new file mode 100644
index 00000000..7eb305e8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HeadTimestampRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HeadTimestampRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HeadTimestampRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aHeadTimestampRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xdc\x01\n\x14HeadTimestampRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x13\n\x06useRTH\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x17\n\nwhatToShow\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x17\n\nformatDate\x18\x05 \x01(\x05H\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\t\n\x07_useRTHB\r\n\x0b_whatToShowB\r\n\x0b_formatDateBD\n\x16\x63om.ib.client.protobufB\x19HeadTimestampRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HeadTimestampRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031HeadTimestampRequestProto\252\002\016IBApi.protobuf'
+ _globals['_HEADTIMESTAMPREQUEST']._serialized_start=57
+ _globals['_HEADTIMESTAMPREQUEST']._serialized_end=277
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HeadTimestamp_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HeadTimestamp_pb2.py
new file mode 100644
index 00000000..f548e064
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HeadTimestamp_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HeadTimestamp.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HeadTimestamp.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13HeadTimestamp.proto\x12\x08protobuf\"[\n\rHeadTimestamp\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1a\n\rheadTimestamp\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x10\n\x0e_headTimestampB=\n\x16\x63om.ib.client.protobufB\x12HeadTimestampProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HeadTimestamp_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022HeadTimestampProto\252\002\016IBApi.protobuf'
+ _globals['_HEADTIMESTAMP']._serialized_start=33
+ _globals['_HEADTIMESTAMP']._serialized_end=124
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramDataEntry_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramDataEntry_pb2.py
new file mode 100644
index 00000000..c1ba47be
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramDataEntry_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistogramDataEntry.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistogramDataEntry.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18HistogramDataEntry.proto\x12\x08protobuf\"N\n\x12HistogramDataEntry\x12\x12\n\x05price\x18\x01 \x01(\x01H\x00\x88\x01\x01\x12\x11\n\x04size\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_priceB\x07\n\x05_sizeBB\n\x16\x63om.ib.client.protobufB\x17HistogramDataEntryProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistogramDataEntry_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027HistogramDataEntryProto\252\002\016IBApi.protobuf'
+ _globals['_HISTOGRAMDATAENTRY']._serialized_start=38
+ _globals['_HISTOGRAMDATAENTRY']._serialized_end=116
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramDataRequest_pb2.py
new file mode 100644
index 00000000..544da633
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramDataRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistogramDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistogramDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aHistogramDataRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xb4\x01\n\x14HistogramDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x13\n\x06useRTH\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x17\n\ntimePeriod\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\t\n\x07_useRTHB\r\n\x0b_timePeriodBD\n\x16\x63om.ib.client.protobufB\x19HistogramDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistogramDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031HistogramDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_HISTOGRAMDATAREQUEST']._serialized_start=57
+ _globals['_HISTOGRAMDATAREQUEST']._serialized_end=237
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramData_pb2.py
new file mode 100644
index 00000000..7059b103
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistogramData_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistogramData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistogramData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistogramDataEntry_pb2 as HistogramDataEntry__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13HistogramData.proto\x12\x08protobuf\x1a\x18HistogramDataEntry.proto\"i\n\rHistogramData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12:\n\x14histogramDataEntries\x18\x02 \x03(\x0b\x32\x1c.protobuf.HistogramDataEntryB\x08\n\x06_reqIdB=\n\x16\x63om.ib.client.protobufB\x12HistogramDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistogramData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022HistogramDataProto\252\002\016IBApi.protobuf'
+ _globals['_HISTOGRAMDATA']._serialized_start=59
+ _globals['_HISTOGRAMDATA']._serialized_end=164
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataBar_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataBar_pb2.py
new file mode 100644
index 00000000..4c3db3f4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataBar_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalDataBar.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalDataBar.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17HistoricalDataBar.proto\x12\x08protobuf\"\xfd\x01\n\x11HistoricalDataBar\x12\x11\n\x04\x64\x61te\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\x04open\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x11\n\x04high\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x10\n\x03low\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x12\n\x05\x63lose\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x13\n\x06volume\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x10\n\x03WAP\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x15\n\x08\x62\x61rCount\x18\x08 \x01(\x05H\x07\x88\x01\x01\x42\x07\n\x05_dateB\x07\n\x05_openB\x07\n\x05_highB\x06\n\x04_lowB\x08\n\x06_closeB\t\n\x07_volumeB\x06\n\x04_WAPB\x0b\n\t_barCountBA\n\x16\x63om.ib.client.protobufB\x16HistoricalDataBarProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalDataBar_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026HistoricalDataBarProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALDATABAR']._serialized_start=38
+ _globals['_HISTORICALDATABAR']._serialized_end=291
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataEnd_pb2.py
new file mode 100644
index 00000000..ab48175b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalDataEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalDataEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17HistoricalDataEnd.proto\x12\x08protobuf\"\x85\x01\n\x11HistoricalDataEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x19\n\x0cstartDateStr\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x17\n\nendDateStr\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0f\n\r_startDateStrB\r\n\x0b_endDateStrBA\n\x16\x63om.ib.client.protobufB\x16HistoricalDataEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalDataEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026HistoricalDataEndProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALDATAEND']._serialized_start=38
+ _globals['_HISTORICALDATAEND']._serialized_end=171
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataRequest_pb2.py
new file mode 100644
index 00000000..1120214f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bHistoricalDataRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\x85\x04\n\x15HistoricalDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x18\n\x0b\x65ndDateTime\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1b\n\x0e\x62\x61rSizeSetting\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08\x64uration\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x13\n\x06useRTH\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x17\n\nwhatToShow\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x17\n\nformatDate\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x19\n\x0ckeepUpToDate\x18\t \x01(\x08H\x08\x88\x01\x01\x12G\n\x0c\x63hartOptions\x18\n \x03(\x0b\x32\x31.protobuf.HistoricalDataRequest.ChartOptionsEntry\x1a\x33\n\x11\x43hartOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x0e\n\x0c_endDateTimeB\x11\n\x0f_barSizeSettingB\x0b\n\t_durationB\t\n\x07_useRTHB\r\n\x0b_whatToShowB\r\n\x0b_formatDateB\x0f\n\r_keepUpToDateBE\n\x16\x63om.ib.client.protobufB\x1aHistoricalDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032HistoricalDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALDATAREQUEST_CHARTOPTIONSENTRY']._loaded_options = None
+ _globals['_HISTORICALDATAREQUEST_CHARTOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_HISTORICALDATAREQUEST']._serialized_start=58
+ _globals['_HISTORICALDATAREQUEST']._serialized_end=575
+ _globals['_HISTORICALDATAREQUEST_CHARTOPTIONSENTRY']._serialized_start=395
+ _globals['_HISTORICALDATAREQUEST_CHARTOPTIONSENTRY']._serialized_end=446
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataUpdate_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataUpdate_pb2.py
new file mode 100644
index 00000000..76538d71
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalDataUpdate_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalDataUpdate.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalDataUpdate.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalDataBar_pb2 as HistoricalDataBar__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aHistoricalDataUpdate.proto\x12\x08protobuf\x1a\x17HistoricalDataBar.proto\"\x87\x01\n\x14HistoricalDataUpdate\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12;\n\x11historicalDataBar\x18\x02 \x01(\x0b\x32\x1b.protobuf.HistoricalDataBarH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x14\n\x12_historicalDataBarBD\n\x16\x63om.ib.client.protobufB\x19HistoricalDataUpdateProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalDataUpdate_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031HistoricalDataUpdateProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALDATAUPDATE']._serialized_start=66
+ _globals['_HISTORICALDATAUPDATE']._serialized_end=201
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalData_pb2.py
new file mode 100644
index 00000000..e7894d61
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalData_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalDataBar_pb2 as HistoricalDataBar__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14HistoricalData.proto\x12\x08protobuf\x1a\x17HistoricalDataBar.proto\"g\n\x0eHistoricalData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x37\n\x12historicalDataBars\x18\x02 \x03(\x0b\x32\x1b.protobuf.HistoricalDataBarB\x08\n\x06_reqIdB>\n\x16\x63om.ib.client.protobufB\x13HistoricalDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023HistoricalDataProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALDATA']._serialized_start=59
+ _globals['_HISTORICALDATA']._serialized_end=162
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNewsEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNewsEnd_pb2.py
new file mode 100644
index 00000000..d8c5a342
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNewsEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalNewsEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalNewsEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17HistoricalNewsEnd.proto\x12\x08protobuf\"S\n\x11HistoricalNewsEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07hasMore\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_hasMoreBA\n\x16\x63om.ib.client.protobufB\x16HistoricalNewsEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalNewsEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026HistoricalNewsEndProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALNEWSEND']._serialized_start=37
+ _globals['_HISTORICALNEWSEND']._serialized_end=120
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNewsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNewsRequest_pb2.py
new file mode 100644
index 00000000..161c0301
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNewsRequest_pb2.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalNewsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalNewsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bHistoricalNewsRequest.proto\x12\x08protobuf\"\x9e\x03\n\x15HistoricalNewsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05\x63onId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x1a\n\rproviderCodes\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rstartDateTime\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x18\n\x0b\x65ndDateTime\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x19\n\x0ctotalResults\x18\x06 \x01(\x05H\x05\x88\x01\x01\x12Y\n\x15historicalNewsOptions\x18\x07 \x03(\x0b\x32:.protobuf.HistoricalNewsRequest.HistoricalNewsOptionsEntry\x1a<\n\x1aHistoricalNewsOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x08\n\x06_conIdB\x10\n\x0e_providerCodesB\x10\n\x0e_startDateTimeB\x0e\n\x0c_endDateTimeB\x0f\n\r_totalResultsBE\n\x16\x63om.ib.client.protobufB\x1aHistoricalNewsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalNewsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032HistoricalNewsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALNEWSREQUEST_HISTORICALNEWSOPTIONSENTRY']._loaded_options = None
+ _globals['_HISTORICALNEWSREQUEST_HISTORICALNEWSOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_HISTORICALNEWSREQUEST']._serialized_start=42
+ _globals['_HISTORICALNEWSREQUEST']._serialized_end=456
+ _globals['_HISTORICALNEWSREQUEST_HISTORICALNEWSOPTIONSENTRY']._serialized_start=307
+ _globals['_HISTORICALNEWSREQUEST_HISTORICALNEWSOPTIONSENTRY']._serialized_end=367
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNews_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNews_pb2.py
new file mode 100644
index 00000000..9e677095
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalNews_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalNews.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalNews.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14HistoricalNews.proto\x12\x08protobuf\"\xc0\x01\n\x0eHistoricalNews\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x11\n\x04time\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0cproviderCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x16\n\tarticleId\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08headline\x18\x05 \x01(\tH\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\x07\n\x05_timeB\x0f\n\r_providerCodeB\x0c\n\n_articleIdB\x0b\n\t_headlineB>\n\x16\x63om.ib.client.protobufB\x13HistoricalNewsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalNews_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023HistoricalNewsProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALNEWS']._serialized_start=35
+ _globals['_HISTORICALNEWS']._serialized_end=227
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalSchedule_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalSchedule_pb2.py
new file mode 100644
index 00000000..7be1c8eb
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalSchedule_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalSchedule.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalSchedule.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalSession_pb2 as HistoricalSession__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18HistoricalSchedule.proto\x12\x08protobuf\x1a\x17HistoricalSession.proto\"\xe7\x01\n\x12HistoricalSchedule\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1a\n\rstartDateTime\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x65ndDateTime\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08timeZone\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x37\n\x12historicalSessions\x18\x05 \x03(\x0b\x32\x1b.protobuf.HistoricalSessionB\x08\n\x06_reqIdB\x10\n\x0e_startDateTimeB\x0e\n\x0c_endDateTimeB\x0b\n\t_timeZoneBB\n\x16\x63om.ib.client.protobufB\x17HistoricalScheduleProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalSchedule_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027HistoricalScheduleProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALSCHEDULE']._serialized_start=64
+ _globals['_HISTORICALSCHEDULE']._serialized_end=295
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalSession_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalSession_pb2.py
new file mode 100644
index 00000000..4ebf948e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalSession_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalSession.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalSession.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17HistoricalSession.proto\x12\x08protobuf\"\x8d\x01\n\x11HistoricalSession\x12\x1a\n\rstartDateTime\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x65ndDateTime\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07refDate\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x10\n\x0e_startDateTimeB\x0e\n\x0c_endDateTimeB\n\n\x08_refDateBA\n\x16\x63om.ib.client.protobufB\x16HistoricalSessionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalSession_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026HistoricalSessionProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALSESSION']._serialized_start=38
+ _globals['_HISTORICALSESSION']._serialized_end=179
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTickBidAsk_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTickBidAsk_pb2.py
new file mode 100644
index 00000000..e5269eb9
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTickBidAsk_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTickBidAsk.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTickBidAsk.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.TickAttribBidAsk_pb2 as TickAttribBidAsk__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aHistoricalTickBidAsk.proto\x12\x08protobuf\x1a\x16TickAttribBidAsk.proto\"\x8e\x02\n\x14HistoricalTickBidAsk\x12\x11\n\x04time\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x39\n\x10tickAttribBidAsk\x18\x02 \x01(\x0b\x32\x1a.protobuf.TickAttribBidAskH\x01\x88\x01\x01\x12\x15\n\x08priceBid\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x15\n\x08priceAsk\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x14\n\x07sizeBid\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x14\n\x07sizeAsk\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\x07\n\x05_timeB\x13\n\x11_tickAttribBidAskB\x0b\n\t_priceBidB\x0b\n\t_priceAskB\n\n\x08_sizeBidB\n\n\x08_sizeAskBD\n\x16\x63om.ib.client.protobufB\x19HistoricalTickBidAskProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTickBidAsk_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031HistoricalTickBidAskProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICKBIDASK']._serialized_start=65
+ _globals['_HISTORICALTICKBIDASK']._serialized_end=335
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTickLast_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTickLast_pb2.py
new file mode 100644
index 00000000..0d245140
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTickLast_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTickLast.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTickLast.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.TickAttribLast_pb2 as TickAttribLast__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18HistoricalTickLast.proto\x12\x08protobuf\x1a\x14TickAttribLast.proto\"\x8e\x02\n\x12HistoricalTickLast\x12\x11\n\x04time\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x35\n\x0etickAttribLast\x18\x02 \x01(\x0b\x32\x18.protobuf.TickAttribLastH\x01\x88\x01\x01\x12\x12\n\x05price\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x11\n\x04size\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x1e\n\x11specialConditions\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\x07\n\x05_timeB\x11\n\x0f_tickAttribLastB\x08\n\x06_priceB\x07\n\x05_sizeB\x0b\n\t_exchangeB\x14\n\x12_specialConditionsBB\n\x16\x63om.ib.client.protobufB\x17HistoricalTickLastProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTickLast_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027HistoricalTickLastProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICKLAST']._serialized_start=61
+ _globals['_HISTORICALTICKLAST']._serialized_end=331
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTick_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTick_pb2.py
new file mode 100644
index 00000000..45f156a6
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTick_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTick.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTick.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14HistoricalTick.proto\x12\x08protobuf\"f\n\x0eHistoricalTick\x12\x11\n\x04time\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x12\n\x05price\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x11\n\x04size\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x07\n\x05_timeB\x08\n\x06_priceB\x07\n\x05_sizeB>\n\x16\x63om.ib.client.protobufB\x13HistoricalTickProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTick_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023HistoricalTickProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICK']._serialized_start=34
+ _globals['_HISTORICALTICK']._serialized_end=136
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksBidAsk_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksBidAsk_pb2.py
new file mode 100644
index 00000000..9e887c09
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksBidAsk_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTicksBidAsk.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTicksBidAsk.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalTickBidAsk_pb2 as HistoricalTickBidAsk__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bHistoricalTicksBidAsk.proto\x12\x08protobuf\x1a\x1aHistoricalTickBidAsk.proto\"\x94\x01\n\x15HistoricalTicksBidAsk\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12=\n\x15historicalTicksBidAsk\x18\x02 \x03(\x0b\x32\x1e.protobuf.HistoricalTickBidAsk\x12\x13\n\x06isDone\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\t\n\x07_isDoneBE\n\x16\x63om.ib.client.protobufB\x1aHistoricalTicksBidAskProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTicksBidAsk_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032HistoricalTicksBidAskProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICKSBIDASK']._serialized_start=70
+ _globals['_HISTORICALTICKSBIDASK']._serialized_end=218
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksLast_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksLast_pb2.py
new file mode 100644
index 00000000..ec6a33a1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksLast_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTicksLast.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTicksLast.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalTickLast_pb2 as HistoricalTickLast__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19HistoricalTicksLast.proto\x12\x08protobuf\x1a\x18HistoricalTickLast.proto\"\x8e\x01\n\x13HistoricalTicksLast\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x39\n\x13historicalTicksLast\x18\x02 \x03(\x0b\x32\x1c.protobuf.HistoricalTickLast\x12\x13\n\x06isDone\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\t\n\x07_isDoneBC\n\x16\x63om.ib.client.protobufB\x18HistoricalTicksLastProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTicksLast_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030HistoricalTicksLastProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICKSLAST']._serialized_start=66
+ _globals['_HISTORICALTICKSLAST']._serialized_end=208
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksRequest_pb2.py
new file mode 100644
index 00000000..538a6be8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicksRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTicksRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTicksRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cHistoricalTicksRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xe0\x03\n\x16HistoricalTicksRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x1a\n\rstartDateTime\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x18\n\x0b\x65ndDateTime\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1a\n\rnumberOfTicks\x18\x05 \x01(\x05H\x04\x88\x01\x01\x12\x17\n\nwhatToShow\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x13\n\x06useRTH\x18\x07 \x01(\x08H\x06\x88\x01\x01\x12\x17\n\nignoreSize\x18\x08 \x01(\x08H\x07\x88\x01\x01\x12\x46\n\x0bmiscOptions\x18\t \x03(\x0b\x32\x31.protobuf.HistoricalTicksRequest.MiscOptionsEntry\x1a\x32\n\x10MiscOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x10\n\x0e_startDateTimeB\x0e\n\x0c_endDateTimeB\x10\n\x0e_numberOfTicksB\r\n\x0b_whatToShowB\t\n\x07_useRTHB\r\n\x0b_ignoreSizeBF\n\x16\x63om.ib.client.protobufB\x1bHistoricalTicksRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTicksRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033HistoricalTicksRequestProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICKSREQUEST_MISCOPTIONSENTRY']._loaded_options = None
+ _globals['_HISTORICALTICKSREQUEST_MISCOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_HISTORICALTICKSREQUEST']._serialized_start=59
+ _globals['_HISTORICALTICKSREQUEST']._serialized_end=539
+ _globals['_HISTORICALTICKSREQUEST_MISCOPTIONSENTRY']._serialized_start=373
+ _globals['_HISTORICALTICKSREQUEST_MISCOPTIONSENTRY']._serialized_end=423
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicks_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicks_pb2.py
new file mode 100644
index 00000000..27a5c1d9
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/HistoricalTicks_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: HistoricalTicks.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'HistoricalTicks.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalTick_pb2 as HistoricalTick__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15HistoricalTicks.proto\x12\x08protobuf\x1a\x14HistoricalTick.proto\"\x82\x01\n\x0fHistoricalTicks\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x31\n\x0fhistoricalTicks\x18\x02 \x03(\x0b\x32\x18.protobuf.HistoricalTick\x12\x13\n\x06isDone\x18\x03 \x01(\x08H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\t\n\x07_isDoneB?\n\x16\x63om.ib.client.protobufB\x14HistoricalTicksProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'HistoricalTicks_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024HistoricalTicksProto\252\002\016IBApi.protobuf'
+ _globals['_HISTORICALTICKS']._serialized_start=58
+ _globals['_HISTORICALTICKS']._serialized_end=188
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/IdsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/IdsRequest_pb2.py
new file mode 100644
index 00000000..865f19d4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/IdsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: IdsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'IdsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10IdsRequest.proto\x12\x08protobuf\",\n\nIdsRequest\x12\x13\n\x06numIds\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\t\n\x07_numIdsB:\n\x16\x63om.ib.client.protobufB\x0fIdsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'IdsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017IdsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_IDSREQUEST']._serialized_start=30
+ _globals['_IDSREQUEST']._serialized_end=74
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/IneligibilityReason_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/IneligibilityReason_pb2.py
new file mode 100644
index 00000000..8516ff41
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/IneligibilityReason_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: IneligibilityReason.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'IneligibilityReason.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19IneligibilityReason.proto\x12\x08protobuf\"W\n\x13IneligibilityReason\x12\x0f\n\x02id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x64\x65scription\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x05\n\x03_idB\x0e\n\x0c_descriptionBC\n\x16\x63om.ib.client.protobufB\x18IneligibilityReasonProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'IneligibilityReason_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030IneligibilityReasonProto\252\002\016IBApi.protobuf'
+ _globals['_INELIGIBILITYREASON']._serialized_start=39
+ _globals['_INELIGIBILITYREASON']._serialized_end=126
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/LockAndExitConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/LockAndExitConfig_pb2.py
new file mode 100644
index 00000000..ab0ab7a9
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/LockAndExitConfig_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: LockAndExitConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'LockAndExitConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17LockAndExitConfig.proto\x12\x08protobuf\"\xa7\x01\n\x11LockAndExitConfig\x12\x1b\n\x0e\x61utoLogoffTime\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1d\n\x10\x61utoLogoffPeriod\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1b\n\x0e\x61utoLogoffType\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x11\n\x0f_autoLogoffTimeB\x13\n\x11_autoLogoffPeriodB\x11\n\x0f_autoLogoffTypeBA\n\x16\x63om.ib.client.protobufB\x16LockAndExitConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'LockAndExitConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026LockAndExitConfigProto\252\002\016IBApi.protobuf'
+ _globals['_LOCKANDEXITCONFIG']._serialized_start=38
+ _globals['_LOCKANDEXITCONFIG']._serialized_end=205
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ManagedAccountsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ManagedAccountsRequest_pb2.py
new file mode 100644
index 00000000..d7927096
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ManagedAccountsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ManagedAccountsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ManagedAccountsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cManagedAccountsRequest.proto\x12\x08protobuf\"\x18\n\x16ManagedAccountsRequestBF\n\x16\x63om.ib.client.protobufB\x1bManagedAccountsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ManagedAccountsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033ManagedAccountsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MANAGEDACCOUNTSREQUEST']._serialized_start=42
+ _globals['_MANAGEDACCOUNTSREQUEST']._serialized_end=66
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ManagedAccounts_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ManagedAccounts_pb2.py
new file mode 100644
index 00000000..f6959517
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ManagedAccounts_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ManagedAccounts.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ManagedAccounts.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15ManagedAccounts.proto\x12\x08protobuf\"=\n\x0fManagedAccounts\x12\x19\n\x0c\x61\x63\x63ountsList\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_accountsListB?\n\x16\x63om.ib.client.protobufB\x14ManagedAccountsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ManagedAccounts_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024ManagedAccountsProto\252\002\016IBApi.protobuf'
+ _globals['_MANAGEDACCOUNTS']._serialized_start=35
+ _globals['_MANAGEDACCOUNTS']._serialized_end=96
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataRequest_pb2.py
new file mode 100644
index 00000000..049af649
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17MarketDataRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\x80\x03\n\x11MarketDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x1c\n\x0fgenericTickList\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08snapshot\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x1f\n\x12regulatorySnapshot\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12M\n\x11marketDataOptions\x18\x06 \x03(\x0b\x32\x32.protobuf.MarketDataRequest.MarketDataOptionsEntry\x1a\x38\n\x16MarketDataOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x12\n\x10_genericTickListB\x0b\n\t_snapshotB\x15\n\x13_regulatorySnapshotBA\n\x16\x63om.ib.client.protobufB\x16MarketDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026MarketDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDATAREQUEST_MARKETDATAOPTIONSENTRY']._loaded_options = None
+ _globals['_MARKETDATAREQUEST_MARKETDATAOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_MARKETDATAREQUEST']._serialized_start=54
+ _globals['_MARKETDATAREQUEST']._serialized_end=438
+ _globals['_MARKETDATAREQUEST_MARKETDATAOPTIONSENTRY']._serialized_start=303
+ _globals['_MARKETDATAREQUEST_MARKETDATAOPTIONSENTRY']._serialized_end=359
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataTypeRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataTypeRequest_pb2.py
new file mode 100644
index 00000000..543bc6a1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataTypeRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDataTypeRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDataTypeRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bMarketDataTypeRequest.proto\x12\x08protobuf\"G\n\x15MarketDataTypeRequest\x12\x1b\n\x0emarketDataType\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x11\n\x0f_marketDataTypeBE\n\x16\x63om.ib.client.protobufB\x1aMarketDataTypeRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDataTypeRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032MarketDataTypeRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDATATYPEREQUEST']._serialized_start=41
+ _globals['_MARKETDATATYPEREQUEST']._serialized_end=112
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataType_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataType_pb2.py
new file mode 100644
index 00000000..a2dd445e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDataType_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDataType.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDataType.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14MarketDataType.proto\x12\x08protobuf\"^\n\x0eMarketDataType\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1b\n\x0emarketDataType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x11\n\x0f_marketDataTypeB>\n\x16\x63om.ib.client.protobufB\x13MarketDataTypeProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDataType_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023MarketDataTypeProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDATATYPE']._serialized_start=34
+ _globals['_MARKETDATATYPE']._serialized_end=128
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthData_pb2.py
new file mode 100644
index 00000000..d3b42f6c
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDepthData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDepthData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15MarketDepthData.proto\x12\x08protobuf\"\x87\x02\n\x0fMarketDepthData\x12\x15\n\x08position\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\toperation\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x11\n\x04side\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x12\n\x05price\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x11\n\x04size\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x18\n\x0bmarketMaker\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x19\n\x0cisSmartDepth\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\x0b\n\t_positionB\x0c\n\n_operationB\x07\n\x05_sideB\x08\n\x06_priceB\x07\n\x05_sizeB\x0e\n\x0c_marketMakerB\x0f\n\r_isSmartDepthB?\n\x16\x63om.ib.client.protobufB\x14MarketDepthDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDepthData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024MarketDepthDataProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDEPTHDATA']._serialized_start=36
+ _globals['_MARKETDEPTHDATA']._serialized_end=299
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthExchangesRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthExchangesRequest_pb2.py
new file mode 100644
index 00000000..a255092e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthExchangesRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDepthExchangesRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDepthExchangesRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!MarketDepthExchangesRequest.proto\x12\x08protobuf\"\x1d\n\x1bMarketDepthExchangesRequestBK\n\x16\x63om.ib.client.protobufB MarketDepthExchangesRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDepthExchangesRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB MarketDepthExchangesRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDEPTHEXCHANGESREQUEST']._serialized_start=47
+ _globals['_MARKETDEPTHEXCHANGESREQUEST']._serialized_end=76
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthExchanges_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthExchanges_pb2.py
new file mode 100644
index 00000000..dcb77a4e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthExchanges_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDepthExchanges.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDepthExchanges.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.DepthMarketDataDescription_pb2 as DepthMarketDataDescription__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aMarketDepthExchanges.proto\x12\x08protobuf\x1a DepthMarketDataDescription.proto\"a\n\x14MarketDepthExchanges\x12I\n\x1b\x64\x65pthMarketDataDescriptions\x18\x01 \x03(\x0b\x32$.protobuf.DepthMarketDataDescriptionBD\n\x16\x63om.ib.client.protobufB\x19MarketDepthExchangesProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDepthExchanges_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031MarketDepthExchangesProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDEPTHEXCHANGES']._serialized_start=74
+ _globals['_MARKETDEPTHEXCHANGES']._serialized_end=171
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthL2_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthL2_pb2.py
new file mode 100644
index 00000000..de63b1cf
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthL2_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDepthL2.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDepthL2.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.MarketDepthData_pb2 as MarketDepthData__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13MarketDepthL2.proto\x12\x08protobuf\x1a\x15MarketDepthData.proto\"z\n\rMarketDepthL2\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x37\n\x0fmarketDepthData\x18\x02 \x01(\x0b\x32\x19.protobuf.MarketDepthDataH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x12\n\x10_marketDepthDataB=\n\x16\x63om.ib.client.protobufB\x12MarketDepthL2Proto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDepthL2_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022MarketDepthL2Proto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDEPTHL2']._serialized_start=56
+ _globals['_MARKETDEPTHL2']._serialized_end=178
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthRequest_pb2.py
new file mode 100644
index 00000000..cfc4d03b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepthRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDepthRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDepthRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18MarketDepthRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xc5\x02\n\x12MarketDepthRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x14\n\x07numRows\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x19\n\x0cisSmartDepth\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12P\n\x12marketDepthOptions\x18\x05 \x03(\x0b\x32\x34.protobuf.MarketDepthRequest.MarketDepthOptionsEntry\x1a\x39\n\x17MarketDepthOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\n\n\x08_numRowsB\x0f\n\r_isSmartDepthBB\n\x16\x63om.ib.client.protobufB\x17MarketDepthRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDepthRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027MarketDepthRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDEPTHREQUEST_MARKETDEPTHOPTIONSENTRY']._loaded_options = None
+ _globals['_MARKETDEPTHREQUEST_MARKETDEPTHOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_MARKETDEPTHREQUEST']._serialized_start=55
+ _globals['_MARKETDEPTHREQUEST']._serialized_end=380
+ _globals['_MARKETDEPTHREQUEST_MARKETDEPTHOPTIONSENTRY']._serialized_start=271
+ _globals['_MARKETDEPTHREQUEST_MARKETDEPTHOPTIONSENTRY']._serialized_end=328
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepth_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepth_pb2.py
new file mode 100644
index 00000000..e76fa275
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketDepth_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketDepth.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketDepth.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.MarketDepthData_pb2 as MarketDepthData__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11MarketDepth.proto\x12\x08protobuf\x1a\x15MarketDepthData.proto\"x\n\x0bMarketDepth\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x37\n\x0fmarketDepthData\x18\x02 \x01(\x0b\x32\x19.protobuf.MarketDepthDataH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x12\n\x10_marketDepthDataB;\n\x16\x63om.ib.client.protobufB\x10MarketDepthProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketDepth_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020MarketDepthProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETDEPTH']._serialized_start=54
+ _globals['_MARKETDEPTH']._serialized_end=174
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketRuleRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketRuleRequest_pb2.py
new file mode 100644
index 00000000..cbe2cdb6
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketRuleRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketRuleRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketRuleRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17MarketRuleRequest.proto\x12\x08protobuf\"?\n\x11MarketRuleRequest\x12\x19\n\x0cmarketRuleId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x0f\n\r_marketRuleIdBA\n\x16\x63om.ib.client.protobufB\x16MarketRuleRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketRuleRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026MarketRuleRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETRULEREQUEST']._serialized_start=37
+ _globals['_MARKETRULEREQUEST']._serialized_end=100
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketRule_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketRule_pb2.py
new file mode 100644
index 00000000..d979bcfa
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MarketRule_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MarketRule.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MarketRule.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.PriceIncrement_pb2 as PriceIncrement__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10MarketRule.proto\x12\x08protobuf\x1a\x14PriceIncrement.proto\"k\n\nMarketRule\x12\x19\n\x0cmarketRuleId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x31\n\x0fpriceIncrements\x18\x02 \x03(\x0b\x32\x18.protobuf.PriceIncrementB\x0f\n\r_marketRuleIdB:\n\x16\x63om.ib.client.protobufB\x0fMarketRuleProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MarketRule_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017MarketRuleProto\252\002\016IBApi.protobuf'
+ _globals['_MARKETRULE']._serialized_start=52
+ _globals['_MARKETRULE']._serialized_end=159
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MatchingSymbolsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MatchingSymbolsRequest_pb2.py
new file mode 100644
index 00000000..6eda23ce
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MatchingSymbolsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MatchingSymbolsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MatchingSymbolsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cMatchingSymbolsRequest.proto\x12\x08protobuf\"X\n\x16MatchingSymbolsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07pattern\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_patternBF\n\x16\x63om.ib.client.protobufB\x1bMatchingSymbolsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MatchingSymbolsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033MatchingSymbolsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_MATCHINGSYMBOLSREQUEST']._serialized_start=42
+ _globals['_MATCHINGSYMBOLSREQUEST']._serialized_end=130
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MessageConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MessageConfig_pb2.py
new file mode 100644
index 00000000..98e58ad5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/MessageConfig_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: MessageConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'MessageConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13MessageConfig.proto\x12\x08protobuf\"\xb7\x01\n\rMessageConfig\x12\x0f\n\x02id\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05title\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07message\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rdefaultAction\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x14\n\x07\x65nabled\x18\x05 \x01(\x08H\x04\x88\x01\x01\x42\x05\n\x03_idB\x08\n\x06_titleB\n\n\x08_messageB\x10\n\x0e_defaultActionB\n\n\x08_enabledB=\n\x16\x63om.ib.client.protobufB\x12MessageConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'MessageConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022MessageConfigProto\252\002\016IBApi.protobuf'
+ _globals['_MESSAGECONFIG']._serialized_start=34
+ _globals['_MESSAGECONFIG']._serialized_end=217
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsArticleRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsArticleRequest_pb2.py
new file mode 100644
index 00000000..61f75bf7
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsArticleRequest_pb2.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsArticleRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsArticleRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18NewsArticleRequest.proto\x12\x08protobuf\"\x91\x02\n\x12NewsArticleRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x19\n\x0cproviderCode\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tarticleId\x18\x03 \x01(\tH\x02\x88\x01\x01\x12P\n\x12newsArticleOptions\x18\x04 \x03(\x0b\x32\x34.protobuf.NewsArticleRequest.NewsArticleOptionsEntry\x1a\x39\n\x17NewsArticleOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0f\n\r_providerCodeB\x0c\n\n_articleIdBB\n\x16\x63om.ib.client.protobufB\x17NewsArticleRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsArticleRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027NewsArticleRequestProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSARTICLEREQUEST_NEWSARTICLEOPTIONSENTRY']._loaded_options = None
+ _globals['_NEWSARTICLEREQUEST_NEWSARTICLEOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_NEWSARTICLEREQUEST']._serialized_start=39
+ _globals['_NEWSARTICLEREQUEST']._serialized_end=312
+ _globals['_NEWSARTICLEREQUEST_NEWSARTICLEOPTIONSENTRY']._serialized_start=214
+ _globals['_NEWSARTICLEREQUEST_NEWSARTICLEOPTIONSENTRY']._serialized_end=271
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsArticle_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsArticle_pb2.py
new file mode 100644
index 00000000..1eb5d1b2
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsArticle_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsArticle.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsArticle.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11NewsArticle.proto\x12\x08protobuf\"\x7f\n\x0bNewsArticle\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x18\n\x0b\x61rticleType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x18\n\x0b\x61rticleText\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0e\n\x0c_articleTypeB\x0e\n\x0c_articleTextB;\n\x16\x63om.ib.client.protobufB\x10NewsArticleProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsArticle_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020NewsArticleProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSARTICLE']._serialized_start=31
+ _globals['_NEWSARTICLE']._serialized_end=158
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsBulletin_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsBulletin_pb2.py
new file mode 100644
index 00000000..28e92fc2
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsBulletin_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsBulletin.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsBulletin.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12NewsBulletin.proto\x12\x08protobuf\"\xba\x01\n\x0cNewsBulletin\x12\x16\n\tnewsMsgId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x18\n\x0bnewsMsgType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x18\n\x0bnewsMessage\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1c\n\x0foriginatingExch\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x0c\n\n_newsMsgIdB\x0e\n\x0c_newsMsgTypeB\x0e\n\x0c_newsMessageB\x12\n\x10_originatingExchB<\n\x16\x63om.ib.client.protobufB\x11NewsBulletinProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsBulletin_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021NewsBulletinProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSBULLETIN']._serialized_start=33
+ _globals['_NEWSBULLETIN']._serialized_end=219
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsBulletinsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsBulletinsRequest_pb2.py
new file mode 100644
index 00000000..5b1405ca
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsBulletinsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsBulletinsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsBulletinsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aNewsBulletinsRequest.proto\x12\x08protobuf\"@\n\x14NewsBulletinsRequest\x12\x18\n\x0b\x61llMessages\x18\x01 \x01(\x08H\x00\x88\x01\x01\x42\x0e\n\x0c_allMessagesBD\n\x16\x63om.ib.client.protobufB\x19NewsBulletinsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsBulletinsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031NewsBulletinsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSBULLETINSREQUEST']._serialized_start=40
+ _globals['_NEWSBULLETINSREQUEST']._serialized_end=104
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProvider_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProvider_pb2.py
new file mode 100644
index 00000000..f33a12e1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProvider_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsProvider.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsProvider.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12NewsProvider.proto\x12\x08protobuf\"f\n\x0cNewsProvider\x12\x19\n\x0cproviderCode\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x19\n\x0cproviderName\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0f\n\r_providerCodeB\x0f\n\r_providerNameB<\n\x16\x63om.ib.client.protobufB\x11NewsProviderProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsProvider_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021NewsProviderProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSPROVIDER']._serialized_start=32
+ _globals['_NEWSPROVIDER']._serialized_end=134
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProvidersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProvidersRequest_pb2.py
new file mode 100644
index 00000000..f5ea1647
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProvidersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsProvidersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsProvidersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aNewsProvidersRequest.proto\x12\x08protobuf\"\x16\n\x14NewsProvidersRequestBD\n\x16\x63om.ib.client.protobufB\x19NewsProvidersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsProvidersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031NewsProvidersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSPROVIDERSREQUEST']._serialized_start=40
+ _globals['_NEWSPROVIDERSREQUEST']._serialized_end=62
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProviders_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProviders_pb2.py
new file mode 100644
index 00000000..d22d08d2
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NewsProviders_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NewsProviders.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NewsProviders.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.NewsProvider_pb2 as NewsProvider__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13NewsProviders.proto\x12\x08protobuf\x1a\x12NewsProvider.proto\">\n\rNewsProviders\x12-\n\rnewsProviders\x18\x01 \x03(\x0b\x32\x16.protobuf.NewsProviderB=\n\x16\x63om.ib.client.protobufB\x12NewsProvidersProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NewsProviders_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022NewsProvidersProto\252\002\016IBApi.protobuf'
+ _globals['_NEWSPROVIDERS']._serialized_start=53
+ _globals['_NEWSPROVIDERS']._serialized_end=115
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NextValidId_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NextValidId_pb2.py
new file mode 100644
index 00000000..2dcbaea7
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/NextValidId_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: NextValidId.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'NextValidId.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11NextValidId.proto\x12\x08protobuf\"/\n\x0bNextValidId\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\n\n\x08_orderIdB;\n\x16\x63om.ib.client.protobufB\x10NextValidIdProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'NextValidId_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020NextValidIdProto\252\002\016IBApi.protobuf'
+ _globals['_NEXTVALIDID']._serialized_start=31
+ _globals['_NEXTVALIDID']._serialized_end=78
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrder_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrder_pb2.py
new file mode 100644
index 00000000..3ae3910b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrder_pb2.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OpenOrder.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OpenOrder.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+import ibapi.protobuf.Order_pb2 as Order__pb2
+import ibapi.protobuf.OrderState_pb2 as OrderState__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fOpenOrder.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\x1a\x0bOrder.proto\x1a\x10OrderState.proto\"\xd2\x01\n\tOpenOrder\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12#\n\x05order\x18\x03 \x01(\x0b\x32\x0f.protobuf.OrderH\x02\x88\x01\x01\x12-\n\norderState\x18\x04 \x01(\x0b\x32\x14.protobuf.OrderStateH\x03\x88\x01\x01\x42\n\n\x08_orderIdB\x0b\n\t_contractB\x08\n\x06_orderB\r\n\x0b_orderStateB9\n\x16\x63om.ib.client.protobufB\x0eOpenOrderProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OpenOrder_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016OpenOrderProto\252\002\016IBApi.protobuf'
+ _globals['_OPENORDER']._serialized_start=77
+ _globals['_OPENORDER']._serialized_end=287
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrdersEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrdersEnd_pb2.py
new file mode 100644
index 00000000..64099351
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrdersEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OpenOrdersEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OpenOrdersEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13OpenOrdersEnd.proto\x12\x08protobuf\"\x0f\n\rOpenOrdersEndB=\n\x16\x63om.ib.client.protobufB\x12OpenOrdersEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OpenOrdersEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022OpenOrdersEndProto\252\002\016IBApi.protobuf'
+ _globals['_OPENORDERSEND']._serialized_start=33
+ _globals['_OPENORDERSEND']._serialized_end=48
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrdersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrdersRequest_pb2.py
new file mode 100644
index 00000000..d1ae95eb
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OpenOrdersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OpenOrdersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OpenOrdersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17OpenOrdersRequest.proto\x12\x08protobuf\"\x13\n\x11OpenOrdersRequestBA\n\x16\x63om.ib.client.protobufB\x16OpenOrdersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OpenOrdersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026OpenOrdersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_OPENORDERSREQUEST']._serialized_start=37
+ _globals['_OPENORDERSREQUEST']._serialized_end=56
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderAllocation_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderAllocation_pb2.py
new file mode 100644
index 00000000..d1eb92aa
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderAllocation_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrderAllocation.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrderAllocation.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15OrderAllocation.proto\x12\x08protobuf\"\xc3\x02\n\x0fOrderAllocation\x12\x14\n\x07\x61\x63\x63ount\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x15\n\x08position\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1c\n\x0fpositionDesired\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rpositionAfter\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1c\n\x0f\x64\x65siredAllocQty\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x1c\n\x0f\x61llowedAllocQty\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x17\n\nisMonetary\x18\x07 \x01(\x08H\x06\x88\x01\x01\x42\n\n\x08_accountB\x0b\n\t_positionB\x12\n\x10_positionDesiredB\x10\n\x0e_positionAfterB\x12\n\x10_desiredAllocQtyB\x12\n\x10_allowedAllocQtyB\r\n\x0b_isMonetaryB?\n\x16\x63om.ib.client.protobufB\x14OrderAllocationProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrderAllocation_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024OrderAllocationProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERALLOCATION']._serialized_start=36
+ _globals['_ORDERALLOCATION']._serialized_end=359
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderBound_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderBound_pb2.py
new file mode 100644
index 00000000..31297fec
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderBound_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrderBound.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrderBound.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10OrderBound.proto\x12\x08protobuf\"r\n\nOrderBound\x12\x13\n\x06permId\x18\x01 \x01(\x03H\x00\x88\x01\x01\x12\x15\n\x08\x63lientId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x14\n\x07orderId\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\t\n\x07_permIdB\x0b\n\t_clientIdB\n\n\x08_orderIdB:\n\x16\x63om.ib.client.protobufB\x0fOrderBoundProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrderBound_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017OrderBoundProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERBOUND']._serialized_start=30
+ _globals['_ORDERBOUND']._serialized_end=144
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderCancel_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderCancel_pb2.py
new file mode 100644
index 00000000..66b5b27e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderCancel_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrderCancel.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrderCancel.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11OrderCancel.proto\x12\x08protobuf\"\xb1\x01\n\x0bOrderCancel\x12\"\n\x15manualOrderCancelTime\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x18\n\x0b\x65xtOperator\x18\x02 \x01(\tH\x01\x88\x01\x01\x12!\n\x14manualOrderIndicator\x18\x03 \x01(\x05H\x02\x88\x01\x01\x42\x18\n\x16_manualOrderCancelTimeB\x0e\n\x0c_extOperatorB\x17\n\x15_manualOrderIndicatorB;\n\x16\x63om.ib.client.protobufB\x10OrderCancelProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrderCancel_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020OrderCancelProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERCANCEL']._serialized_start=32
+ _globals['_ORDERCANCEL']._serialized_end=209
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderCondition_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderCondition_pb2.py
new file mode 100644
index 00000000..885a37b5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderCondition_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrderCondition.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrderCondition.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14OrderCondition.proto\x12\x08protobuf\"\xea\x03\n\x0eOrderCondition\x12\x11\n\x04type\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12$\n\x17isConjunctionConnection\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\x13\n\x06isMore\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x12\n\x05\x63onId\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x13\n\x06symbol\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x14\n\x07secType\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x14\n\x07percent\x18\x08 \x01(\x05H\x07\x88\x01\x01\x12\x1a\n\rchangePercent\x18\t \x01(\x01H\x08\x88\x01\x01\x12\x12\n\x05price\x18\n \x01(\x01H\t\x88\x01\x01\x12\x1a\n\rtriggerMethod\x18\x0b \x01(\x05H\n\x88\x01\x01\x12\x11\n\x04time\x18\x0c \x01(\tH\x0b\x88\x01\x01\x12\x13\n\x06volume\x18\r \x01(\x05H\x0c\x88\x01\x01\x42\x07\n\x05_typeB\x1a\n\x18_isConjunctionConnectionB\t\n\x07_isMoreB\x08\n\x06_conIdB\x0b\n\t_exchangeB\t\n\x07_symbolB\n\n\x08_secTypeB\n\n\x08_percentB\x10\n\x0e_changePercentB\x08\n\x06_priceB\x10\n\x0e_triggerMethodB\x07\n\x05_timeB\t\n\x07_volumeB>\n\x16\x63om.ib.client.protobufB\x13OrderConditionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrderCondition_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023OrderConditionProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERCONDITION']._serialized_start=35
+ _globals['_ORDERCONDITION']._serialized_end=525
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderState_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderState_pb2.py
new file mode 100644
index 00000000..d77b0c4b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderState_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrderState.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrderState.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.OrderAllocation_pb2 as OrderAllocation__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10OrderState.proto\x12\x08protobuf\x1a\x15OrderAllocation.proto\"\xf5\r\n\nOrderState\x12\x13\n\x06status\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x1d\n\x10initMarginBefore\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x1e\n\x11maintMarginBefore\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12!\n\x14\x65quityWithLoanBefore\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x1d\n\x10initMarginChange\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x1e\n\x11maintMarginChange\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12!\n\x14\x65quityWithLoanChange\x18\x07 \x01(\x01H\x06\x88\x01\x01\x12\x1c\n\x0finitMarginAfter\x18\x08 \x01(\x01H\x07\x88\x01\x01\x12\x1d\n\x10maintMarginAfter\x18\t \x01(\x01H\x08\x88\x01\x01\x12 \n\x13\x65quityWithLoanAfter\x18\n \x01(\x01H\t\x88\x01\x01\x12\x1e\n\x11\x63ommissionAndFees\x18\x0b \x01(\x01H\n\x88\x01\x01\x12!\n\x14minCommissionAndFees\x18\x0c \x01(\x01H\x0b\x88\x01\x01\x12!\n\x14maxCommissionAndFees\x18\r \x01(\x01H\x0c\x88\x01\x01\x12&\n\x19\x63ommissionAndFeesCurrency\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x1b\n\x0emarginCurrency\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\'\n\x1ainitMarginBeforeOutsideRTH\x18\x10 \x01(\x01H\x0f\x88\x01\x01\x12(\n\x1bmaintMarginBeforeOutsideRTH\x18\x11 \x01(\x01H\x10\x88\x01\x01\x12+\n\x1e\x65quityWithLoanBeforeOutsideRTH\x18\x12 \x01(\x01H\x11\x88\x01\x01\x12\'\n\x1ainitMarginChangeOutsideRTH\x18\x13 \x01(\x01H\x12\x88\x01\x01\x12(\n\x1bmaintMarginChangeOutsideRTH\x18\x14 \x01(\x01H\x13\x88\x01\x01\x12+\n\x1e\x65quityWithLoanChangeOutsideRTH\x18\x15 \x01(\x01H\x14\x88\x01\x01\x12&\n\x19initMarginAfterOutsideRTH\x18\x16 \x01(\x01H\x15\x88\x01\x01\x12\'\n\x1amaintMarginAfterOutsideRTH\x18\x17 \x01(\x01H\x16\x88\x01\x01\x12*\n\x1d\x65quityWithLoanAfterOutsideRTH\x18\x18 \x01(\x01H\x17\x88\x01\x01\x12\x1a\n\rsuggestedSize\x18\x19 \x01(\tH\x18\x88\x01\x01\x12\x19\n\x0crejectReason\x18\x1a \x01(\tH\x19\x88\x01\x01\x12\x33\n\x10orderAllocations\x18\x1b \x03(\x0b\x32\x19.protobuf.OrderAllocation\x12\x18\n\x0bwarningText\x18\x1c \x01(\tH\x1a\x88\x01\x01\x12\x1a\n\rcompletedTime\x18\x1d \x01(\tH\x1b\x88\x01\x01\x12\x1c\n\x0f\x63ompletedStatus\x18\x1e \x01(\tH\x1c\x88\x01\x01\x42\t\n\x07_statusB\x13\n\x11_initMarginBeforeB\x14\n\x12_maintMarginBeforeB\x17\n\x15_equityWithLoanBeforeB\x13\n\x11_initMarginChangeB\x14\n\x12_maintMarginChangeB\x17\n\x15_equityWithLoanChangeB\x12\n\x10_initMarginAfterB\x13\n\x11_maintMarginAfterB\x16\n\x14_equityWithLoanAfterB\x14\n\x12_commissionAndFeesB\x17\n\x15_minCommissionAndFeesB\x17\n\x15_maxCommissionAndFeesB\x1c\n\x1a_commissionAndFeesCurrencyB\x11\n\x0f_marginCurrencyB\x1d\n\x1b_initMarginBeforeOutsideRTHB\x1e\n\x1c_maintMarginBeforeOutsideRTHB!\n\x1f_equityWithLoanBeforeOutsideRTHB\x1d\n\x1b_initMarginChangeOutsideRTHB\x1e\n\x1c_maintMarginChangeOutsideRTHB!\n\x1f_equityWithLoanChangeOutsideRTHB\x1c\n\x1a_initMarginAfterOutsideRTHB\x1d\n\x1b_maintMarginAfterOutsideRTHB \n\x1e_equityWithLoanAfterOutsideRTHB\x10\n\x0e_suggestedSizeB\x0f\n\r_rejectReasonB\x0e\n\x0c_warningTextB\x10\n\x0e_completedTimeB\x12\n\x10_completedStatusB:\n\x16\x63om.ib.client.protobufB\x0fOrderStateProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrderState_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017OrderStateProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERSTATE']._serialized_start=54
+ _globals['_ORDERSTATE']._serialized_end=1835
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderStatus_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderStatus_pb2.py
new file mode 100644
index 00000000..274dcd8d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrderStatus_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrderStatus.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrderStatus.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11OrderStatus.proto\x12\x08protobuf\"\xa3\x03\n\x0bOrderStatus\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x13\n\x06status\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x13\n\x06\x66illed\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x16\n\tremaining\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x19\n\x0c\x61vgFillPrice\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x13\n\x06permId\x18\x06 \x01(\x03H\x05\x88\x01\x01\x12\x15\n\x08parentId\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x1a\n\rlastFillPrice\x18\x08 \x01(\x01H\x07\x88\x01\x01\x12\x15\n\x08\x63lientId\x18\t \x01(\x05H\x08\x88\x01\x01\x12\x14\n\x07whyHeld\x18\n \x01(\tH\t\x88\x01\x01\x12\x18\n\x0bmktCapPrice\x18\x0b \x01(\x01H\n\x88\x01\x01\x42\n\n\x08_orderIdB\t\n\x07_statusB\t\n\x07_filledB\x0c\n\n_remainingB\x0f\n\r_avgFillPriceB\t\n\x07_permIdB\x0b\n\t_parentIdB\x10\n\x0e_lastFillPriceB\x0b\n\t_clientIdB\n\n\x08_whyHeldB\x0e\n\x0c_mktCapPriceB;\n\x16\x63om.ib.client.protobufB\x10OrderStatusProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrderStatus_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020OrderStatusProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERSTATUS']._serialized_start=32
+ _globals['_ORDERSTATUS']._serialized_end=451
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Order_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Order_pb2.py
new file mode 100644
index 00000000..9b8f6df7
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Order_pb2.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: Order.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'Order.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.OrderCondition_pb2 as OrderCondition__pb2
+import ibapi.protobuf.SoftDollarTier_pb2 as SoftDollarTier__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0bOrder.proto\x12\x08protobuf\x1a\x14OrderCondition.proto\x1a\x14SoftDollarTier.proto\"\xdd\x38\n\x05Order\x12\x15\n\x08\x63lientId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07orderId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06permId\x18\x03 \x01(\x03H\x02\x88\x01\x01\x12\x15\n\x08parentId\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12\x13\n\x06\x61\x63tion\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x1a\n\rtotalQuantity\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x18\n\x0b\x64isplaySize\x18\x07 \x01(\x05H\x06\x88\x01\x01\x12\x16\n\torderType\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x15\n\x08lmtPrice\x18\t \x01(\x01H\x08\x88\x01\x01\x12\x15\n\x08\x61uxPrice\x18\n \x01(\x01H\t\x88\x01\x01\x12\x10\n\x03tif\x18\x0b \x01(\tH\n\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x0c \x01(\tH\x0b\x88\x01\x01\x12\x19\n\x0csettlingFirm\x18\r \x01(\tH\x0c\x88\x01\x01\x12\x1c\n\x0f\x63learingAccount\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x1b\n\x0e\x63learingIntent\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x16\n\tallOrNone\x18\x10 \x01(\x08H\x0f\x88\x01\x01\x12\x17\n\nblockOrder\x18\x11 \x01(\x08H\x10\x88\x01\x01\x12\x13\n\x06hidden\x18\x12 \x01(\x08H\x11\x88\x01\x01\x12\x17\n\noutsideRth\x18\x13 \x01(\x08H\x12\x88\x01\x01\x12\x18\n\x0bsweepToFill\x18\x14 \x01(\x08H\x13\x88\x01\x01\x12\x1a\n\rpercentOffset\x18\x15 \x01(\x01H\x14\x88\x01\x01\x12\x1c\n\x0ftrailingPercent\x18\x16 \x01(\x01H\x15\x88\x01\x01\x12\x1b\n\x0etrailStopPrice\x18\x17 \x01(\x01H\x16\x88\x01\x01\x12\x13\n\x06minQty\x18\x18 \x01(\x05H\x17\x88\x01\x01\x12\x1a\n\rgoodAfterTime\x18\x19 \x01(\tH\x18\x88\x01\x01\x12\x19\n\x0cgoodTillDate\x18\x1a \x01(\tH\x19\x88\x01\x01\x12\x15\n\x08ocaGroup\x18\x1b \x01(\tH\x1a\x88\x01\x01\x12\x15\n\x08orderRef\x18\x1c \x01(\tH\x1b\x88\x01\x01\x12\x14\n\x07rule80A\x18\x1d \x01(\tH\x1c\x88\x01\x01\x12\x14\n\x07ocaType\x18\x1e \x01(\x05H\x1d\x88\x01\x01\x12\x1a\n\rtriggerMethod\x18\x1f \x01(\x05H\x1e\x88\x01\x01\x12\x1c\n\x0f\x61\x63tiveStartTime\x18 \x01(\tH\x1f\x88\x01\x01\x12\x1b\n\x0e\x61\x63tiveStopTime\x18! \x01(\tH \x88\x01\x01\x12\x14\n\x07\x66\x61Group\x18\" \x01(\tH!\x88\x01\x01\x12\x15\n\x08\x66\x61Method\x18# \x01(\tH\"\x88\x01\x01\x12\x19\n\x0c\x66\x61Percentage\x18$ \x01(\tH#\x88\x01\x01\x12\x17\n\nvolatility\x18% \x01(\x01H$\x88\x01\x01\x12\x1b\n\x0evolatilityType\x18& \x01(\x05H%\x88\x01\x01\x12\x1d\n\x10\x63ontinuousUpdate\x18\' \x01(\x08H&\x88\x01\x01\x12\x1f\n\x12referencePriceType\x18( \x01(\x05H\'\x88\x01\x01\x12\"\n\x15\x64\x65ltaNeutralOrderType\x18) \x01(\tH(\x88\x01\x01\x12!\n\x14\x64\x65ltaNeutralAuxPrice\x18* \x01(\x01H)\x88\x01\x01\x12\x1e\n\x11\x64\x65ltaNeutralConId\x18+ \x01(\x05H*\x88\x01\x01\x12\"\n\x15\x64\x65ltaNeutralOpenClose\x18, \x01(\tH+\x88\x01\x01\x12\"\n\x15\x64\x65ltaNeutralShortSale\x18- \x01(\x08H,\x88\x01\x01\x12&\n\x19\x64\x65ltaNeutralShortSaleSlot\x18. \x01(\x05H-\x88\x01\x01\x12+\n\x1e\x64\x65ltaNeutralDesignatedLocation\x18/ \x01(\tH.\x88\x01\x01\x12\x1f\n\x12scaleInitLevelSize\x18\x30 \x01(\x05H/\x88\x01\x01\x12\x1f\n\x12scaleSubsLevelSize\x18\x31 \x01(\x05H0\x88\x01\x01\x12 \n\x13scalePriceIncrement\x18\x32 \x01(\x01H1\x88\x01\x01\x12\"\n\x15scalePriceAdjustValue\x18\x33 \x01(\x01H2\x88\x01\x01\x12%\n\x18scalePriceAdjustInterval\x18\x34 \x01(\x05H3\x88\x01\x01\x12\x1e\n\x11scaleProfitOffset\x18\x35 \x01(\x01H4\x88\x01\x01\x12\x1b\n\x0escaleAutoReset\x18\x36 \x01(\x08H5\x88\x01\x01\x12\x1e\n\x11scaleInitPosition\x18\x37 \x01(\x05H6\x88\x01\x01\x12\x1d\n\x10scaleInitFillQty\x18\x38 \x01(\x05H7\x88\x01\x01\x12\x1f\n\x12scaleRandomPercent\x18\x39 \x01(\x08H8\x88\x01\x01\x12\x17\n\nscaleTable\x18: \x01(\tH9\x88\x01\x01\x12\x16\n\thedgeType\x18; \x01(\tH:\x88\x01\x01\x12\x17\n\nhedgeParam\x18< \x01(\tH;\x88\x01\x01\x12\x19\n\x0c\x61lgoStrategy\x18= \x01(\tH<\x88\x01\x01\x12\x33\n\nalgoParams\x18> \x03(\x0b\x32\x1f.protobuf.Order.AlgoParamsEntry\x12\x13\n\x06\x61lgoId\x18? \x01(\tH=\x88\x01\x01\x12M\n\x17smartComboRoutingParams\x18@ \x03(\x0b\x32,.protobuf.Order.SmartComboRoutingParamsEntry\x12\x13\n\x06whatIf\x18\x41 \x01(\x08H>\x88\x01\x01\x12\x15\n\x08transmit\x18\x42 \x01(\x08H?\x88\x01\x01\x12*\n\x1doverridePercentageConstraints\x18\x43 \x01(\x08H@\x88\x01\x01\x12\x16\n\topenClose\x18\x44 \x01(\tHA\x88\x01\x01\x12\x13\n\x06origin\x18\x45 \x01(\x05HB\x88\x01\x01\x12\x1a\n\rshortSaleSlot\x18\x46 \x01(\x05HC\x88\x01\x01\x12\x1f\n\x12\x64\x65signatedLocation\x18G \x01(\tHD\x88\x01\x01\x12\x17\n\nexemptCode\x18H \x01(\x05HE\x88\x01\x01\x12%\n\x18\x64\x65ltaNeutralSettlingFirm\x18I \x01(\tHF\x88\x01\x01\x12(\n\x1b\x64\x65ltaNeutralClearingAccount\x18J \x01(\tHG\x88\x01\x01\x12\'\n\x1a\x64\x65ltaNeutralClearingIntent\x18K \x01(\tHH\x88\x01\x01\x12\x1d\n\x10\x64iscretionaryAmt\x18L \x01(\x01HI\x88\x01\x01\x12\x1f\n\x12optOutSmartRouting\x18M \x01(\x08HJ\x88\x01\x01\x12\x1a\n\rstartingPrice\x18N \x01(\x01HK\x88\x01\x01\x12\x1a\n\rstockRefPrice\x18O \x01(\x01HL\x88\x01\x01\x12\x12\n\x05\x64\x65lta\x18P \x01(\x01HM\x88\x01\x01\x12\x1c\n\x0fstockRangeLower\x18Q \x01(\x01HN\x88\x01\x01\x12\x1c\n\x0fstockRangeUpper\x18R \x01(\x01HO\x88\x01\x01\x12\x14\n\x07notHeld\x18S \x01(\x08HP\x88\x01\x01\x12?\n\x10orderMiscOptions\x18T \x03(\x0b\x32%.protobuf.Order.OrderMiscOptionsEntry\x12\x16\n\tsolicited\x18U \x01(\x08HQ\x88\x01\x01\x12\x1a\n\rrandomizeSize\x18V \x01(\x08HR\x88\x01\x01\x12\x1b\n\x0erandomizePrice\x18W \x01(\x08HS\x88\x01\x01\x12 \n\x13referenceContractId\x18X \x01(\x05HT\x88\x01\x01\x12\x1f\n\x12peggedChangeAmount\x18Y \x01(\x01HU\x88\x01\x01\x12)\n\x1cisPeggedChangeAmountDecrease\x18Z \x01(\x08HV\x88\x01\x01\x12\"\n\x15referenceChangeAmount\x18[ \x01(\x01HW\x88\x01\x01\x12 \n\x13referenceExchangeId\x18\\ \x01(\tHX\x88\x01\x01\x12\x1e\n\x11\x61\x64justedOrderType\x18] \x01(\tHY\x88\x01\x01\x12\x19\n\x0ctriggerPrice\x18^ \x01(\x01HZ\x88\x01\x01\x12\x1e\n\x11\x61\x64justedStopPrice\x18_ \x01(\x01H[\x88\x01\x01\x12#\n\x16\x61\x64justedStopLimitPrice\x18` \x01(\x01H\\\x88\x01\x01\x12#\n\x16\x61\x64justedTrailingAmount\x18\x61 \x01(\x01H]\x88\x01\x01\x12#\n\x16\x61\x64justableTrailingUnit\x18\x62 \x01(\x05H^\x88\x01\x01\x12\x1b\n\x0elmtPriceOffset\x18\x63 \x01(\x01H_\x88\x01\x01\x12,\n\nconditions\x18\x64 \x03(\x0b\x32\x18.protobuf.OrderCondition\x12\"\n\x15\x63onditionsCancelOrder\x18\x65 \x01(\x08H`\x88\x01\x01\x12 \n\x13\x63onditionsIgnoreRth\x18\x66 \x01(\x08Ha\x88\x01\x01\x12\x16\n\tmodelCode\x18g \x01(\tHb\x88\x01\x01\x12\x18\n\x0b\x65xtOperator\x18h \x01(\tHc\x88\x01\x01\x12\x35\n\x0esoftDollarTier\x18i \x01(\x0b\x32\x18.protobuf.SoftDollarTierHd\x88\x01\x01\x12\x14\n\x07\x63\x61shQty\x18j \x01(\x01He\x88\x01\x01\x12 \n\x13mifid2DecisionMaker\x18k \x01(\tHf\x88\x01\x01\x12\x1f\n\x12mifid2DecisionAlgo\x18l \x01(\tHg\x88\x01\x01\x12\"\n\x15mifid2ExecutionTrader\x18m \x01(\tHh\x88\x01\x01\x12 \n\x13mifid2ExecutionAlgo\x18n \x01(\tHi\x88\x01\x01\x12%\n\x18\x64ontUseAutoPriceForHedge\x18o \x01(\x08Hj\x88\x01\x01\x12\x1b\n\x0eisOmsContainer\x18p \x01(\x08Hk\x88\x01\x01\x12(\n\x1b\x64iscretionaryUpToLimitPrice\x18q \x01(\x08Hl\x88\x01\x01\x12\x1b\n\x0e\x61utoCancelDate\x18r \x01(\tHm\x88\x01\x01\x12\x1b\n\x0e\x66illedQuantity\x18s \x01(\tHn\x88\x01\x01\x12\x1c\n\x0frefFuturesConId\x18t \x01(\x05Ho\x88\x01\x01\x12\x1d\n\x10\x61utoCancelParent\x18u \x01(\x08Hp\x88\x01\x01\x12\x18\n\x0bshareholder\x18v \x01(\tHq\x88\x01\x01\x12\x1a\n\rimbalanceOnly\x18w \x01(\x08Hr\x88\x01\x01\x12!\n\x14routeMarketableToBbo\x18x \x01(\x05Hs\x88\x01\x01\x12\x19\n\x0cparentPermId\x18y \x01(\x03Ht\x88\x01\x01\x12\x1d\n\x10usePriceMgmtAlgo\x18z \x01(\x05Hu\x88\x01\x01\x12\x15\n\x08\x64uration\x18{ \x01(\x05Hv\x88\x01\x01\x12\x16\n\tpostToAts\x18| \x01(\x05Hw\x88\x01\x01\x12\"\n\x15\x61\x64vancedErrorOverride\x18} \x01(\tHx\x88\x01\x01\x12\x1c\n\x0fmanualOrderTime\x18~ \x01(\tHy\x88\x01\x01\x12\x18\n\x0bminTradeQty\x18\x7f \x01(\x05Hz\x88\x01\x01\x12\x1c\n\x0eminCompeteSize\x18\x80\x01 \x01(\x05H{\x88\x01\x01\x12&\n\x18\x63ompeteAgainstBestOffset\x18\x81\x01 \x01(\x01H|\x88\x01\x01\x12\x1e\n\x10midOffsetAtWhole\x18\x82\x01 \x01(\x01H}\x88\x01\x01\x12\x1d\n\x0fmidOffsetAtHalf\x18\x83\x01 \x01(\x01H~\x88\x01\x01\x12\x1d\n\x0f\x63ustomerAccount\x18\x84\x01 \x01(\tH\x7f\x88\x01\x01\x12#\n\x14professionalCustomer\x18\x85\x01 \x01(\x08H\x80\x01\x88\x01\x01\x12\"\n\x13\x62ondAccruedInterest\x18\x86\x01 \x01(\tH\x81\x01\x88\x01\x01\x12\x1f\n\x10includeOvernight\x18\x87\x01 \x01(\x08H\x82\x01\x88\x01\x01\x12#\n\x14manualOrderIndicator\x18\x88\x01 \x01(\x05H\x83\x01\x88\x01\x01\x12\x18\n\tsubmitter\x18\x89\x01 \x01(\tH\x84\x01\x88\x01\x01\x12\x19\n\ndeactivate\x18\x8a\x01 \x01(\x08H\x85\x01\x88\x01\x01\x12\x17\n\x08postOnly\x18\x8b\x01 \x01(\x08H\x86\x01\x88\x01\x01\x12\x1b\n\x0c\x61llowPreOpen\x18\x8c\x01 \x01(\x08H\x87\x01\x88\x01\x01\x12 \n\x11ignoreOpenAuction\x18\x8d\x01 \x01(\x08H\x88\x01\x88\x01\x01\x12#\n\x14seekPriceImprovement\x18\x8e\x01 \x01(\x05H\x89\x01\x88\x01\x01\x12\x19\n\nwhatIfType\x18\x8f\x01 \x01(\x05H\x8a\x01\x88\x01\x01\x1a\x31\n\x0f\x41lgoParamsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a>\n\x1cSmartComboRoutingParamsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x37\n\x15OrderMiscOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0b\n\t_clientIdB\n\n\x08_orderIdB\t\n\x07_permIdB\x0b\n\t_parentIdB\t\n\x07_actionB\x10\n\x0e_totalQuantityB\x0e\n\x0c_displaySizeB\x0c\n\n_orderTypeB\x0b\n\t_lmtPriceB\x0b\n\t_auxPriceB\x06\n\x04_tifB\n\n\x08_accountB\x0f\n\r_settlingFirmB\x12\n\x10_clearingAccountB\x11\n\x0f_clearingIntentB\x0c\n\n_allOrNoneB\r\n\x0b_blockOrderB\t\n\x07_hiddenB\r\n\x0b_outsideRthB\x0e\n\x0c_sweepToFillB\x10\n\x0e_percentOffsetB\x12\n\x10_trailingPercentB\x11\n\x0f_trailStopPriceB\t\n\x07_minQtyB\x10\n\x0e_goodAfterTimeB\x0f\n\r_goodTillDateB\x0b\n\t_ocaGroupB\x0b\n\t_orderRefB\n\n\x08_rule80AB\n\n\x08_ocaTypeB\x10\n\x0e_triggerMethodB\x12\n\x10_activeStartTimeB\x11\n\x0f_activeStopTimeB\n\n\x08_faGroupB\x0b\n\t_faMethodB\x0f\n\r_faPercentageB\r\n\x0b_volatilityB\x11\n\x0f_volatilityTypeB\x13\n\x11_continuousUpdateB\x15\n\x13_referencePriceTypeB\x18\n\x16_deltaNeutralOrderTypeB\x17\n\x15_deltaNeutralAuxPriceB\x14\n\x12_deltaNeutralConIdB\x18\n\x16_deltaNeutralOpenCloseB\x18\n\x16_deltaNeutralShortSaleB\x1c\n\x1a_deltaNeutralShortSaleSlotB!\n\x1f_deltaNeutralDesignatedLocationB\x15\n\x13_scaleInitLevelSizeB\x15\n\x13_scaleSubsLevelSizeB\x16\n\x14_scalePriceIncrementB\x18\n\x16_scalePriceAdjustValueB\x1b\n\x19_scalePriceAdjustIntervalB\x14\n\x12_scaleProfitOffsetB\x11\n\x0f_scaleAutoResetB\x14\n\x12_scaleInitPositionB\x13\n\x11_scaleInitFillQtyB\x15\n\x13_scaleRandomPercentB\r\n\x0b_scaleTableB\x0c\n\n_hedgeTypeB\r\n\x0b_hedgeParamB\x0f\n\r_algoStrategyB\t\n\x07_algoIdB\t\n\x07_whatIfB\x0b\n\t_transmitB \n\x1e_overridePercentageConstraintsB\x0c\n\n_openCloseB\t\n\x07_originB\x10\n\x0e_shortSaleSlotB\x15\n\x13_designatedLocationB\r\n\x0b_exemptCodeB\x1b\n\x19_deltaNeutralSettlingFirmB\x1e\n\x1c_deltaNeutralClearingAccountB\x1d\n\x1b_deltaNeutralClearingIntentB\x13\n\x11_discretionaryAmtB\x15\n\x13_optOutSmartRoutingB\x10\n\x0e_startingPriceB\x10\n\x0e_stockRefPriceB\x08\n\x06_deltaB\x12\n\x10_stockRangeLowerB\x12\n\x10_stockRangeUpperB\n\n\x08_notHeldB\x0c\n\n_solicitedB\x10\n\x0e_randomizeSizeB\x11\n\x0f_randomizePriceB\x16\n\x14_referenceContractIdB\x15\n\x13_peggedChangeAmountB\x1f\n\x1d_isPeggedChangeAmountDecreaseB\x18\n\x16_referenceChangeAmountB\x16\n\x14_referenceExchangeIdB\x14\n\x12_adjustedOrderTypeB\x0f\n\r_triggerPriceB\x14\n\x12_adjustedStopPriceB\x19\n\x17_adjustedStopLimitPriceB\x19\n\x17_adjustedTrailingAmountB\x19\n\x17_adjustableTrailingUnitB\x11\n\x0f_lmtPriceOffsetB\x18\n\x16_conditionsCancelOrderB\x16\n\x14_conditionsIgnoreRthB\x0c\n\n_modelCodeB\x0e\n\x0c_extOperatorB\x11\n\x0f_softDollarTierB\n\n\x08_cashQtyB\x16\n\x14_mifid2DecisionMakerB\x15\n\x13_mifid2DecisionAlgoB\x18\n\x16_mifid2ExecutionTraderB\x16\n\x14_mifid2ExecutionAlgoB\x1b\n\x19_dontUseAutoPriceForHedgeB\x11\n\x0f_isOmsContainerB\x1e\n\x1c_discretionaryUpToLimitPriceB\x11\n\x0f_autoCancelDateB\x11\n\x0f_filledQuantityB\x12\n\x10_refFuturesConIdB\x13\n\x11_autoCancelParentB\x0e\n\x0c_shareholderB\x10\n\x0e_imbalanceOnlyB\x17\n\x15_routeMarketableToBboB\x0f\n\r_parentPermIdB\x13\n\x11_usePriceMgmtAlgoB\x0b\n\t_durationB\x0c\n\n_postToAtsB\x18\n\x16_advancedErrorOverrideB\x12\n\x10_manualOrderTimeB\x0e\n\x0c_minTradeQtyB\x11\n\x0f_minCompeteSizeB\x1b\n\x19_competeAgainstBestOffsetB\x13\n\x11_midOffsetAtWholeB\x12\n\x10_midOffsetAtHalfB\x12\n\x10_customerAccountB\x17\n\x15_professionalCustomerB\x16\n\x14_bondAccruedInterestB\x13\n\x11_includeOvernightB\x17\n\x15_manualOrderIndicatorB\x0c\n\n_submitterB\r\n\x0b_deactivateB\x0b\n\t_postOnlyB\x0f\n\r_allowPreOpenB\x14\n\x12_ignoreOpenAuctionB\x17\n\x15_seekPriceImprovementB\r\n\x0b_whatIfTypeB5\n\x16\x63om.ib.client.protobufB\nOrderProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'Order_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\nOrderProto\252\002\016IBApi.protobuf'
+ _globals['_ORDER_ALGOPARAMSENTRY']._loaded_options = None
+ _globals['_ORDER_ALGOPARAMSENTRY']._serialized_options = b'8\001'
+ _globals['_ORDER_SMARTCOMBOROUTINGPARAMSENTRY']._loaded_options = None
+ _globals['_ORDER_SMARTCOMBOROUTINGPARAMSENTRY']._serialized_options = b'8\001'
+ _globals['_ORDER_ORDERMISCOPTIONSENTRY']._loaded_options = None
+ _globals['_ORDER_ORDERMISCOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_ORDER']._serialized_start=70
+ _globals['_ORDER']._serialized_end=7331
+ _globals['_ORDER_ALGOPARAMSENTRY']._serialized_start=4463
+ _globals['_ORDER_ALGOPARAMSENTRY']._serialized_end=4512
+ _globals['_ORDER_SMARTCOMBOROUTINGPARAMSENTRY']._serialized_start=4514
+ _globals['_ORDER_SMARTCOMBOROUTINGPARAMSENTRY']._serialized_end=4576
+ _globals['_ORDER_ORDERMISCOPTIONSENTRY']._serialized_start=4578
+ _globals['_ORDER_ORDERMISCOPTIONSENTRY']._serialized_end=4633
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrdersConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrdersConfig_pb2.py
new file mode 100644
index 00000000..e94141a1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrdersConfig_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrdersConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrdersConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.OrdersSmartRoutingConfig_pb2 as OrdersSmartRoutingConfig__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12OrdersConfig.proto\x12\x08protobuf\x1a\x1eOrdersSmartRoutingConfig.proto\"H\n\x0cOrdersConfig\x12\x38\n\x0csmartRouting\x18\x01 \x01(\x0b\x32\".protobuf.OrdersSmartRoutingConfigB<\n\x16\x63om.ib.client.protobufB\x11OrdersConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrdersConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021OrdersConfigProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERSCONFIG']._serialized_start=64
+ _globals['_ORDERSCONFIG']._serialized_end=136
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrdersSmartRoutingConfig_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrdersSmartRoutingConfig_pb2.py
new file mode 100644
index 00000000..06e69edc
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/OrdersSmartRoutingConfig_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: OrdersSmartRoutingConfig.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'OrdersSmartRoutingConfig.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eOrdersSmartRoutingConfig.proto\x12\x08protobuf\"\xf8\x01\n\x18OrdersSmartRoutingConfig\x12!\n\x14seekPriceImprovement\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1b\n\x0epreOpenReroute\x18\x02 \x01(\x08H\x01\x88\x01\x01\x12\"\n\x15\x64oNotRouteToDarkPools\x18\x03 \x01(\x08H\x02\x88\x01\x01\x12\x1d\n\x10\x64\x65\x66\x61ultAlgorithm\x18\x04 \x01(\tH\x03\x88\x01\x01\x42\x17\n\x15_seekPriceImprovementB\x11\n\x0f_preOpenRerouteB\x18\n\x16_doNotRouteToDarkPoolsB\x13\n\x11_defaultAlgorithmBH\n\x16\x63om.ib.client.protobufB\x1dOrdersSmartRoutingConfigProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'OrdersSmartRoutingConfig_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\035OrdersSmartRoutingConfigProto\252\002\016IBApi.protobuf'
+ _globals['_ORDERSSMARTROUTINGCONFIG']._serialized_start=45
+ _globals['_ORDERSSMARTROUTINGCONFIG']._serialized_end=293
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PlaceOrderRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PlaceOrderRequest_pb2.py
new file mode 100644
index 00000000..40a0c587
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PlaceOrderRequest_pb2.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PlaceOrderRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PlaceOrderRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+import ibapi.protobuf.Order_pb2 as Order__pb2
+import ibapi.protobuf.AttachedOrders_pb2 as AttachedOrders__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17PlaceOrderRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\x1a\x0bOrder.proto\x1a\x14\x41ttachedOrders.proto\"\xe6\x01\n\x11PlaceOrderRequest\x12\x14\n\x07orderId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12#\n\x05order\x18\x03 \x01(\x0b\x32\x0f.protobuf.OrderH\x02\x88\x01\x01\x12\x35\n\x0e\x61ttachedOrders\x18\x04 \x01(\x0b\x32\x18.protobuf.AttachedOrdersH\x03\x88\x01\x01\x42\n\n\x08_orderIdB\x0b\n\t_contractB\x08\n\x06_orderB\x11\n\x0f_attachedOrdersBA\n\x16\x63om.ib.client.protobufB\x16PlaceOrderRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PlaceOrderRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026PlaceOrderRequestProto\252\002\016IBApi.protobuf'
+ _globals['_PLACEORDERREQUEST']._serialized_start=89
+ _globals['_PLACEORDERREQUEST']._serialized_end=319
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLRequest_pb2.py
new file mode 100644
index 00000000..3b1a6357
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PnLRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PnLRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10PnLRequest.proto\x12\x08protobuf\"r\n\nPnLRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodelCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x0c\n\n_modelCodeB:\n\x16\x63om.ib.client.protobufB\x0fPnLRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PnLRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017PnLRequestProto\252\002\016IBApi.protobuf'
+ _globals['_PNLREQUEST']._serialized_start=30
+ _globals['_PNLREQUEST']._serialized_end=144
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLSingleRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLSingleRequest_pb2.py
new file mode 100644
index 00000000..b366ade0
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLSingleRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PnLSingleRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PnLSingleRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16PnLSingleRequest.proto\x12\x08protobuf\"\x96\x01\n\x10PnLSingleRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodelCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x12\n\x05\x63onId\x18\x04 \x01(\x05H\x03\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x0c\n\n_modelCodeB\x08\n\x06_conIdB@\n\x16\x63om.ib.client.protobufB\x15PnLSingleRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PnLSingleRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025PnLSingleRequestProto\252\002\016IBApi.protobuf'
+ _globals['_PNLSINGLEREQUEST']._serialized_start=37
+ _globals['_PNLSINGLEREQUEST']._serialized_end=187
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLSingle_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLSingle_pb2.py
new file mode 100644
index 00000000..0570da01
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnLSingle_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PnLSingle.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PnLSingle.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fPnLSingle.proto\x12\x08protobuf\"\xe7\x01\n\tPnLSingle\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08position\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x15\n\x08\x64\x61ilyPnL\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x1a\n\runrealizedPnL\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x18\n\x0brealizedPnL\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x12\n\x05value\x18\x06 \x01(\x01H\x05\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_positionB\x0b\n\t_dailyPnLB\x10\n\x0e_unrealizedPnLB\x0e\n\x0c_realizedPnLB\x08\n\x06_valueB9\n\x16\x63om.ib.client.protobufB\x0ePnLSingleProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PnLSingle_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016PnLSingleProto\252\002\016IBApi.protobuf'
+ _globals['_PNLSINGLE']._serialized_start=30
+ _globals['_PNLSINGLE']._serialized_end=261
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnL_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnL_pb2.py
new file mode 100644
index 00000000..c95fced4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PnL_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PnL.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PnL.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tPnL.proto\x12\x08protobuf\"\x9f\x01\n\x03PnL\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x64\x61ilyPnL\x18\x02 \x01(\x01H\x01\x88\x01\x01\x12\x1a\n\runrealizedPnL\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x18\n\x0brealizedPnL\x18\x04 \x01(\x01H\x03\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_dailyPnLB\x10\n\x0e_unrealizedPnLB\x0e\n\x0c_realizedPnLB3\n\x16\x63om.ib.client.protobufB\x08PnLProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PnL_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\010PnLProto\252\002\016IBApi.protobuf'
+ _globals['_PNL']._serialized_start=24
+ _globals['_PNL']._serialized_end=183
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PortfolioValue_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PortfolioValue_pb2.py
new file mode 100644
index 00000000..9869e491
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PortfolioValue_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PortfolioValue.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PortfolioValue.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14PortfolioValue.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xec\x02\n\x0ePortfolioValue\x12)\n\x08\x63ontract\x18\x01 \x01(\x0b\x32\x12.protobuf.ContractH\x00\x88\x01\x01\x12\x15\n\x08position\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0bmarketPrice\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x18\n\x0bmarketValue\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x18\n\x0b\x61verageCost\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x1a\n\runrealizedPNL\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12\x18\n\x0brealizedPNL\x18\x07 \x01(\x01H\x06\x88\x01\x01\x12\x18\n\x0b\x61\x63\x63ountName\x18\x08 \x01(\tH\x07\x88\x01\x01\x42\x0b\n\t_contractB\x0b\n\t_positionB\x0e\n\x0c_marketPriceB\x0e\n\x0c_marketValueB\x0e\n\x0c_averageCostB\x10\n\x0e_unrealizedPNLB\x0e\n\x0c_realizedPNLB\x0e\n\x0c_accountNameB>\n\x16\x63om.ib.client.protobufB\x13PortfolioValueProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PortfolioValue_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023PortfolioValueProto\252\002\016IBApi.protobuf'
+ _globals['_PORTFOLIOVALUE']._serialized_start=51
+ _globals['_PORTFOLIOVALUE']._serialized_end=415
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionEnd_pb2.py
new file mode 100644
index 00000000..eab3ec4a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PositionEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PositionEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11PositionEnd.proto\x12\x08protobuf\"\r\n\x0bPositionEndB;\n\x16\x63om.ib.client.protobufB\x10PositionEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PositionEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020PositionEndProto\252\002\016IBApi.protobuf'
+ _globals['_POSITIONEND']._serialized_start=31
+ _globals['_POSITIONEND']._serialized_end=44
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionMultiEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionMultiEnd_pb2.py
new file mode 100644
index 00000000..cbe93078
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionMultiEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PositionMultiEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PositionMultiEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16PositionMultiEnd.proto\x12\x08protobuf\"0\n\x10PositionMultiEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB@\n\x16\x63om.ib.client.protobufB\x15PositionMultiEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PositionMultiEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025PositionMultiEndProto\252\002\016IBApi.protobuf'
+ _globals['_POSITIONMULTIEND']._serialized_start=36
+ _globals['_POSITIONMULTIEND']._serialized_end=84
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionMulti_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionMulti_pb2.py
new file mode 100644
index 00000000..d82cb48b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionMulti_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PositionMulti.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PositionMulti.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13PositionMulti.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xf3\x01\n\rPositionMulti\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12)\n\x08\x63ontract\x18\x03 \x01(\x0b\x32\x12.protobuf.ContractH\x02\x88\x01\x01\x12\x15\n\x08position\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x14\n\x07\x61vgCost\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x16\n\tmodelCode\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x0b\n\t_contractB\x0b\n\t_positionB\n\n\x08_avgCostB\x0c\n\n_modelCodeB=\n\x16\x63om.ib.client.protobufB\x12PositionMultiProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PositionMulti_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022PositionMultiProto\252\002\016IBApi.protobuf'
+ _globals['_POSITIONMULTI']._serialized_start=50
+ _globals['_POSITIONMULTI']._serialized_end=293
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Position_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Position_pb2.py
new file mode 100644
index 00000000..1a68b81d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/Position_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: Position.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'Position.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0ePosition.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xaa\x01\n\x08Position\x12\x14\n\x07\x61\x63\x63ount\x18\x01 \x01(\tH\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x15\n\x08position\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x14\n\x07\x61vgCost\x18\x04 \x01(\x01H\x03\x88\x01\x01\x42\n\n\x08_accountB\x0b\n\t_contractB\x0b\n\t_positionB\n\n\x08_avgCostB8\n\x16\x63om.ib.client.protobufB\rPositionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'Position_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\rPositionProto\252\002\016IBApi.protobuf'
+ _globals['_POSITION']._serialized_start=45
+ _globals['_POSITION']._serialized_end=215
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionsMultiRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionsMultiRequest_pb2.py
new file mode 100644
index 00000000..fffee63b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionsMultiRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PositionsMultiRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PositionsMultiRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bPositionsMultiRequest.proto\x12\x08protobuf\"}\n\x15PositionsMultiRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07\x61\x63\x63ount\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x16\n\tmodelCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_accountB\x0c\n\n_modelCodeBE\n\x16\x63om.ib.client.protobufB\x1aPositionsMultiRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PositionsMultiRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032PositionsMultiRequestProto\252\002\016IBApi.protobuf'
+ _globals['_POSITIONSMULTIREQUEST']._serialized_start=41
+ _globals['_POSITIONSMULTIREQUEST']._serialized_end=166
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionsRequest_pb2.py
new file mode 100644
index 00000000..bfe1db43
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PositionsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PositionsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PositionsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16PositionsRequest.proto\x12\x08protobuf\"\x12\n\x10PositionsRequestB@\n\x16\x63om.ib.client.protobufB\x15PositionsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PositionsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025PositionsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_POSITIONSREQUEST']._serialized_start=36
+ _globals['_POSITIONSREQUEST']._serialized_end=54
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PriceIncrement_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PriceIncrement_pb2.py
new file mode 100644
index 00000000..8bf9a5ac
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/PriceIncrement_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: PriceIncrement.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'PriceIncrement.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14PriceIncrement.proto\x12\x08protobuf\"X\n\x0ePriceIncrement\x12\x14\n\x07lowEdge\x18\x01 \x01(\x01H\x00\x88\x01\x01\x12\x16\n\tincrement\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\n\n\x08_lowEdgeB\x0c\n\n_incrementB>\n\x16\x63om.ib.client.protobufB\x13PriceIncrementProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'PriceIncrement_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023PriceIncrementProto\252\002\016IBApi.protobuf'
+ _globals['_PRICEINCREMENT']._serialized_start=34
+ _globals['_PRICEINCREMENT']._serialized_end=122
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/QueryDisplayGroupsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/QueryDisplayGroupsRequest_pb2.py
new file mode 100644
index 00000000..cf74a7cd
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/QueryDisplayGroupsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: QueryDisplayGroupsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'QueryDisplayGroupsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fQueryDisplayGroupsRequest.proto\x12\x08protobuf\"9\n\x19QueryDisplayGroupsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBI\n\x16\x63om.ib.client.protobufB\x1eQueryDisplayGroupsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'QueryDisplayGroupsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\036QueryDisplayGroupsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_QUERYDISPLAYGROUPSREQUEST']._serialized_start=45
+ _globals['_QUERYDISPLAYGROUPSREQUEST']._serialized_end=102
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RealTimeBarTick_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RealTimeBarTick_pb2.py
new file mode 100644
index 00000000..2cbb6642
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RealTimeBarTick_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: RealTimeBarTick.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'RealTimeBarTick.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15RealTimeBarTick.proto\x12\x08protobuf\"\x93\x02\n\x0fRealTimeBarTick\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x11\n\x04time\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x11\n\x04open\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x11\n\x04high\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x10\n\x03low\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x12\n\x05\x63lose\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12\x13\n\x06volume\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x10\n\x03WAP\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x12\n\x05\x63ount\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x08\n\x06_reqIdB\x07\n\x05_timeB\x07\n\x05_openB\x07\n\x05_highB\x06\n\x04_lowB\x08\n\x06_closeB\t\n\x07_volumeB\x06\n\x04_WAPB\x08\n\x06_countB?\n\x16\x63om.ib.client.protobufB\x14RealTimeBarTickProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'RealTimeBarTick_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024RealTimeBarTickProto\252\002\016IBApi.protobuf'
+ _globals['_REALTIMEBARTICK']._serialized_start=36
+ _globals['_REALTIMEBARTICK']._serialized_end=311
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RealTimeBarsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RealTimeBarsRequest_pb2.py
new file mode 100644
index 00000000..1cb9ab62
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RealTimeBarsRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: RealTimeBarsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'RealTimeBarsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19RealTimeBarsRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xe6\x02\n\x13RealTimeBarsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x14\n\x07\x62\x61rSize\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x17\n\nwhatToShow\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x13\n\x06useRTH\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12S\n\x13realTimeBarsOptions\x18\x06 \x03(\x0b\x32\x36.protobuf.RealTimeBarsRequest.RealTimeBarsOptionsEntry\x1a:\n\x18RealTimeBarsOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\n\n\x08_barSizeB\r\n\x0b_whatToShowB\t\n\x07_useRTHBC\n\x16\x63om.ib.client.protobufB\x18RealTimeBarsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'RealTimeBarsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030RealTimeBarsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_REALTIMEBARSREQUEST_REALTIMEBARSOPTIONSENTRY']._loaded_options = None
+ _globals['_REALTIMEBARSREQUEST_REALTIMEBARSOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_REALTIMEBARSREQUEST']._serialized_start=56
+ _globals['_REALTIMEBARSREQUEST']._serialized_end=414
+ _globals['_REALTIMEBARSREQUEST_REALTIMEBARSOPTIONSENTRY']._serialized_start=295
+ _globals['_REALTIMEBARSREQUEST_REALTIMEBARSOPTIONSENTRY']._serialized_end=353
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ReceiveFA_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ReceiveFA_pb2.py
new file mode 100644
index 00000000..21911793
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ReceiveFA_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ReceiveFA.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ReceiveFA.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fReceiveFA.proto\x12\x08protobuf\"M\n\tReceiveFA\x12\x17\n\nfaDataType\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x10\n\x03xml\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\r\n\x0b_faDataTypeB\x06\n\x04_xmlB9\n\x16\x63om.ib.client.protobufB\x0eReceiveFAProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ReceiveFA_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016ReceiveFAProto\252\002\016IBApi.protobuf'
+ _globals['_RECEIVEFA']._serialized_start=29
+ _globals['_RECEIVEFA']._serialized_end=106
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ReplaceFAEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ReplaceFAEnd_pb2.py
new file mode 100644
index 00000000..02c26480
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ReplaceFAEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ReplaceFAEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ReplaceFAEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12ReplaceFAEnd.proto\x12\x08protobuf\"H\n\x0cReplaceFAEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x11\n\x04text\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x07\n\x05_textB<\n\x16\x63om.ib.client.protobufB\x11ReplaceFAEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ReplaceFAEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021ReplaceFAEndProto\252\002\016IBApi.protobuf'
+ _globals['_REPLACEFAEND']._serialized_start=32
+ _globals['_REPLACEFAEND']._serialized_end=104
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RerouteMarketDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RerouteMarketDataRequest_pb2.py
new file mode 100644
index 00000000..af0e439e
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RerouteMarketDataRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: RerouteMarketDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'RerouteMarketDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eRerouteMarketDataRequest.proto\x12\x08protobuf\"z\n\x18RerouteMarketDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05\x63onId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x08\n\x06_conIdB\x0b\n\t_exchangeBH\n\x16\x63om.ib.client.protobufB\x1dRerouteMarketDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'RerouteMarketDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\035RerouteMarketDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_REROUTEMARKETDATAREQUEST']._serialized_start=44
+ _globals['_REROUTEMARKETDATAREQUEST']._serialized_end=166
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RerouteMarketDepthRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RerouteMarketDepthRequest_pb2.py
new file mode 100644
index 00000000..2225b582
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/RerouteMarketDepthRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: RerouteMarketDepthRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'RerouteMarketDepthRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fRerouteMarketDepthRequest.proto\x12\x08protobuf\"{\n\x19RerouteMarketDepthRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05\x63onId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x08\n\x06_conIdB\x0b\n\t_exchangeBI\n\x16\x63om.ib.client.protobufB\x1eRerouteMarketDepthRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'RerouteMarketDepthRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\036RerouteMarketDepthRequestProto\252\002\016IBApi.protobuf'
+ _globals['_REROUTEMARKETDEPTHREQUEST']._serialized_start=45
+ _globals['_REROUTEMARKETDEPTHREQUEST']._serialized_end=168
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerDataElement_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerDataElement_pb2.py
new file mode 100644
index 00000000..14e3c7a5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerDataElement_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ScannerDataElement.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ScannerDataElement.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18ScannerDataElement.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xa6\x02\n\x12ScannerDataElement\x12\x11\n\x04rank\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x17\n\nmarketName\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08\x64istance\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x16\n\tbenchmark\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x17\n\nprojection\x18\x06 \x01(\tH\x05\x88\x01\x01\x12\x15\n\x08\x63omboKey\x18\x07 \x01(\tH\x06\x88\x01\x01\x42\x07\n\x05_rankB\x0b\n\t_contractB\r\n\x0b_marketNameB\x0b\n\t_distanceB\x0c\n\n_benchmarkB\r\n\x0b_projectionB\x0b\n\t_comboKeyBB\n\x16\x63om.ib.client.protobufB\x17ScannerDataElementProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ScannerDataElement_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027ScannerDataElementProto\252\002\016IBApi.protobuf'
+ _globals['_SCANNERDATAELEMENT']._serialized_start=55
+ _globals['_SCANNERDATAELEMENT']._serialized_end=349
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerData_pb2.py
new file mode 100644
index 00000000..0c72d05d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerData_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ScannerData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ScannerData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.ScannerDataElement_pb2 as ScannerDataElement__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11ScannerData.proto\x12\x08protobuf\x1a\x18ScannerDataElement.proto\"e\n\x0bScannerData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x38\n\x12scannerDataElement\x18\x02 \x03(\x0b\x32\x1c.protobuf.ScannerDataElementB\x08\n\x06_reqIdB;\n\x16\x63om.ib.client.protobufB\x10ScannerDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ScannerData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020ScannerDataProto\252\002\016IBApi.protobuf'
+ _globals['_SCANNERDATA']._serialized_start=57
+ _globals['_SCANNERDATA']._serialized_end=158
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerParametersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerParametersRequest_pb2.py
new file mode 100644
index 00000000..e6a61b3a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerParametersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ScannerParametersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ScannerParametersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eScannerParametersRequest.proto\x12\x08protobuf\"\x1a\n\x18ScannerParametersRequestBH\n\x16\x63om.ib.client.protobufB\x1dScannerParametersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ScannerParametersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\035ScannerParametersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SCANNERPARAMETERSREQUEST']._serialized_start=44
+ _globals['_SCANNERPARAMETERSREQUEST']._serialized_end=70
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerParameters_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerParameters_pb2.py
new file mode 100644
index 00000000..66491ab6
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerParameters_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ScannerParameters.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ScannerParameters.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17ScannerParameters.proto\x12\x08protobuf\"-\n\x11ScannerParameters\x12\x10\n\x03xml\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\x06\n\x04_xmlBA\n\x16\x63om.ib.client.protobufB\x16ScannerParametersProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ScannerParameters_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026ScannerParametersProto\252\002\016IBApi.protobuf'
+ _globals['_SCANNERPARAMETERS']._serialized_start=37
+ _globals['_SCANNERPARAMETERS']._serialized_end=82
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerSubscriptionRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerSubscriptionRequest_pb2.py
new file mode 100644
index 00000000..ee61d922
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerSubscriptionRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ScannerSubscriptionRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ScannerSubscriptionRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.ScannerSubscription_pb2 as ScannerSubscription__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n ScannerSubscriptionRequest.proto\x12\x08protobuf\x1a\x19ScannerSubscription.proto\"\x93\x01\n\x1aScannerSubscriptionRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12?\n\x13scannerSubscription\x18\x02 \x01(\x0b\x32\x1d.protobuf.ScannerSubscriptionH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x16\n\x14_scannerSubscriptionBJ\n\x16\x63om.ib.client.protobufB\x1fScannerSubscriptionRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ScannerSubscriptionRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\037ScannerSubscriptionRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SCANNERSUBSCRIPTIONREQUEST']._serialized_start=74
+ _globals['_SCANNERSUBSCRIPTIONREQUEST']._serialized_end=221
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerSubscription_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerSubscription_pb2.py
new file mode 100644
index 00000000..33e52c12
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/ScannerSubscription_pb2.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: ScannerSubscription.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'ScannerSubscription.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19ScannerSubscription.proto\x12\x08protobuf\"\xed\n\n\x13ScannerSubscription\x12\x19\n\x0cnumberOfRows\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x17\n\ninstrument\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x19\n\x0clocationCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x15\n\x08scanCode\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x17\n\nabovePrice\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x17\n\nbelowPrice\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12\x18\n\x0b\x61\x62oveVolume\x18\x07 \x01(\x03H\x06\x88\x01\x01\x12\x1b\n\x0emarketCapAbove\x18\x08 \x01(\x01H\x07\x88\x01\x01\x12\x1b\n\x0emarketCapBelow\x18\t \x01(\x01H\x08\x88\x01\x01\x12\x1d\n\x10moodyRatingAbove\x18\n \x01(\tH\t\x88\x01\x01\x12\x1d\n\x10moodyRatingBelow\x18\x0b \x01(\tH\n\x88\x01\x01\x12\x1a\n\rspRatingAbove\x18\x0c \x01(\tH\x0b\x88\x01\x01\x12\x1a\n\rspRatingBelow\x18\r \x01(\tH\x0c\x88\x01\x01\x12\x1e\n\x11maturityDateAbove\x18\x0e \x01(\tH\r\x88\x01\x01\x12\x1e\n\x11maturityDateBelow\x18\x0f \x01(\tH\x0e\x88\x01\x01\x12\x1c\n\x0f\x63ouponRateAbove\x18\x10 \x01(\x01H\x0f\x88\x01\x01\x12\x1c\n\x0f\x63ouponRateBelow\x18\x11 \x01(\x01H\x10\x88\x01\x01\x12\x1f\n\x12\x65xcludeConvertible\x18\x12 \x01(\x08H\x11\x88\x01\x01\x12%\n\x18\x61verageOptionVolumeAbove\x18\x13 \x01(\x03H\x12\x88\x01\x01\x12 \n\x13scannerSettingPairs\x18\x14 \x01(\tH\x13\x88\x01\x01\x12\x1c\n\x0fstockTypeFilter\x18\x15 \x01(\tH\x14\x88\x01\x01\x12m\n scannerSubscriptionFilterOptions\x18\x16 \x03(\x0b\x32\x43.protobuf.ScannerSubscription.ScannerSubscriptionFilterOptionsEntry\x12\x61\n\x1ascannerSubscriptionOptions\x18\x17 \x03(\x0b\x32=.protobuf.ScannerSubscription.ScannerSubscriptionOptionsEntry\x1aG\n%ScannerSubscriptionFilterOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x41\n\x1fScannerSubscriptionOptionsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x0f\n\r_numberOfRowsB\r\n\x0b_instrumentB\x0f\n\r_locationCodeB\x0b\n\t_scanCodeB\r\n\x0b_abovePriceB\r\n\x0b_belowPriceB\x0e\n\x0c_aboveVolumeB\x11\n\x0f_marketCapAboveB\x11\n\x0f_marketCapBelowB\x13\n\x11_moodyRatingAboveB\x13\n\x11_moodyRatingBelowB\x10\n\x0e_spRatingAboveB\x10\n\x0e_spRatingBelowB\x14\n\x12_maturityDateAboveB\x14\n\x12_maturityDateBelowB\x12\n\x10_couponRateAboveB\x12\n\x10_couponRateBelowB\x15\n\x13_excludeConvertibleB\x1b\n\x19_averageOptionVolumeAboveB\x16\n\x14_scannerSettingPairsB\x12\n\x10_stockTypeFilterBC\n\x16\x63om.ib.client.protobufB\x18ScannerSubscriptionProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'ScannerSubscription_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030ScannerSubscriptionProto\252\002\016IBApi.protobuf'
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONFILTEROPTIONSENTRY']._loaded_options = None
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONFILTEROPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONOPTIONSENTRY']._loaded_options = None
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONOPTIONSENTRY']._serialized_options = b'8\001'
+ _globals['_SCANNERSUBSCRIPTION']._serialized_start=40
+ _globals['_SCANNERSUBSCRIPTION']._serialized_end=1429
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONFILTEROPTIONSENTRY']._serialized_start=887
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONFILTEROPTIONSENTRY']._serialized_end=958
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONOPTIONSENTRY']._serialized_start=960
+ _globals['_SCANNERSUBSCRIPTION_SCANNERSUBSCRIPTIONOPTIONSENTRY']._serialized_end=1025
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParameterEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParameterEnd_pb2.py
new file mode 100644
index 00000000..cea28149
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParameterEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SecDefOptParameterEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SecDefOptParameterEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bSecDefOptParameterEnd.proto\x12\x08protobuf\"5\n\x15SecDefOptParameterEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBE\n\x16\x63om.ib.client.protobufB\x1aSecDefOptParameterEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SecDefOptParameterEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032SecDefOptParameterEndProto\252\002\016IBApi.protobuf'
+ _globals['_SECDEFOPTPARAMETEREND']._serialized_start=41
+ _globals['_SECDEFOPTPARAMETEREND']._serialized_end=94
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParameter_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParameter_pb2.py
new file mode 100644
index 00000000..2b39ad67
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParameter_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SecDefOptParameter.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SecDefOptParameter.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18SecDefOptParameter.proto\x12\x08protobuf\"\x82\x02\n\x12SecDefOptParameter\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1c\n\x0funderlyingConId\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x19\n\x0ctradingClass\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x17\n\nmultiplier\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x13\n\x0b\x65xpirations\x18\x06 \x03(\t\x12\x0f\n\x07strikes\x18\x07 \x03(\x01\x42\x08\n\x06_reqIdB\x0b\n\t_exchangeB\x12\n\x10_underlyingConIdB\x0f\n\r_tradingClassB\r\n\x0b_multiplierBB\n\x16\x63om.ib.client.protobufB\x17SecDefOptParameterProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SecDefOptParameter_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027SecDefOptParameterProto\252\002\016IBApi.protobuf'
+ _globals['_SECDEFOPTPARAMETER']._serialized_start=39
+ _globals['_SECDEFOPTPARAMETER']._serialized_end=297
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParamsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParamsRequest_pb2.py
new file mode 100644
index 00000000..8ada3d3a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SecDefOptParamsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SecDefOptParamsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SecDefOptParamsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cSecDefOptParamsRequest.proto\x12\x08protobuf\"\x82\x02\n\x16SecDefOptParamsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1d\n\x10underlyingSymbol\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1b\n\x0e\x66utFopExchange\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1e\n\x11underlyingSecType\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x1c\n\x0funderlyingConId\x18\x05 \x01(\x05H\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\x13\n\x11_underlyingSymbolB\x11\n\x0f_futFopExchangeB\x14\n\x12_underlyingSecTypeB\x12\n\x10_underlyingConIdBF\n\x16\x63om.ib.client.protobufB\x1bSecDefOptParamsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SecDefOptParamsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033SecDefOptParamsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SECDEFOPTPARAMSREQUEST']._serialized_start=43
+ _globals['_SECDEFOPTPARAMSREQUEST']._serialized_end=301
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SetServerLogLevelRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SetServerLogLevelRequest_pb2.py
new file mode 100644
index 00000000..e87df332
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SetServerLogLevelRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SetServerLogLevelRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SetServerLogLevelRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1eSetServerLogLevelRequest.proto\x12\x08protobuf\">\n\x18SetServerLogLevelRequest\x12\x15\n\x08logLevel\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x0b\n\t_logLevelBH\n\x16\x63om.ib.client.protobufB\x1dSetServerLogLevelRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SetServerLogLevelRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\035SetServerLogLevelRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SETSERVERLOGLEVELREQUEST']._serialized_start=44
+ _globals['_SETSERVERLOGLEVELREQUEST']._serialized_end=106
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponent_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponent_pb2.py
new file mode 100644
index 00000000..d9c1468d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponent_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SmartComponent.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SmartComponent.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14SmartComponent.proto\x12\x08protobuf\"\x8a\x01\n\x0eSmartComponent\x12\x16\n\tbitNumber\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x65xchange\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x1b\n\x0e\x65xchangeLetter\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x0c\n\n_bitNumberB\x0b\n\t_exchangeB\x11\n\x0f_exchangeLetterB>\n\x16\x63om.ib.client.protobufB\x13SmartComponentProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SmartComponent_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023SmartComponentProto\252\002\016IBApi.protobuf'
+ _globals['_SMARTCOMPONENT']._serialized_start=35
+ _globals['_SMARTCOMPONENT']._serialized_end=173
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponentsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponentsRequest_pb2.py
new file mode 100644
index 00000000..ba7c1ba9
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponentsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SmartComponentsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SmartComponentsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cSmartComponentsRequest.proto\x12\x08protobuf\"`\n\x16SmartComponentsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x18\n\x0b\x62\x62oExchange\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0e\n\x0c_bboExchangeBF\n\x16\x63om.ib.client.protobufB\x1bSmartComponentsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SmartComponentsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033SmartComponentsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SMARTCOMPONENTSREQUEST']._serialized_start=42
+ _globals['_SMARTCOMPONENTSREQUEST']._serialized_end=138
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponents_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponents_pb2.py
new file mode 100644
index 00000000..b2bf21ef
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SmartComponents_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SmartComponents.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SmartComponents.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.SmartComponent_pb2 as SmartComponent__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15SmartComponents.proto\x12\x08protobuf\x1a\x14SmartComponent.proto\"b\n\x0fSmartComponents\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x31\n\x0fsmartComponents\x18\x02 \x03(\x0b\x32\x18.protobuf.SmartComponentB\x08\n\x06_reqIdB?\n\x16\x63om.ib.client.protobufB\x14SmartComponentsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SmartComponents_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024SmartComponentsProto\252\002\016IBApi.protobuf'
+ _globals['_SMARTCOMPONENTS']._serialized_start=57
+ _globals['_SMARTCOMPONENTS']._serialized_end=155
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTier_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTier_pb2.py
new file mode 100644
index 00000000..7f9f6cf3
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTier_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SoftDollarTier.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SoftDollarTier.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14SoftDollarTier.proto\x12\x08protobuf\"t\n\x0eSoftDollarTier\x12\x11\n\x04name\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x12\n\x05value\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x64isplayName\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x07\n\x05_nameB\x08\n\x06_valueB\x0e\n\x0c_displayNameB>\n\x16\x63om.ib.client.protobufB\x13SoftDollarTierProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SoftDollarTier_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023SoftDollarTierProto\252\002\016IBApi.protobuf'
+ _globals['_SOFTDOLLARTIER']._serialized_start=34
+ _globals['_SOFTDOLLARTIER']._serialized_end=150
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTiersRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTiersRequest_pb2.py
new file mode 100644
index 00000000..219e0f97
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTiersRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SoftDollarTiersRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SoftDollarTiersRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cSoftDollarTiersRequest.proto\x12\x08protobuf\"6\n\x16SoftDollarTiersRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBF\n\x16\x63om.ib.client.protobufB\x1bSoftDollarTiersRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SoftDollarTiersRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\033SoftDollarTiersRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SOFTDOLLARTIERSREQUEST']._serialized_start=42
+ _globals['_SOFTDOLLARTIERSREQUEST']._serialized_end=96
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTiers_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTiers_pb2.py
new file mode 100644
index 00000000..2b8f3be4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SoftDollarTiers_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SoftDollarTiers.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SoftDollarTiers.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.SoftDollarTier_pb2 as SoftDollarTier__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15SoftDollarTiers.proto\x12\x08protobuf\x1a\x14SoftDollarTier.proto\"b\n\x0fSoftDollarTiers\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x31\n\x0fsoftDollarTiers\x18\x02 \x03(\x0b\x32\x18.protobuf.SoftDollarTierB\x08\n\x06_reqIdB?\n\x16\x63om.ib.client.protobufB\x14SoftDollarTiersProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SoftDollarTiers_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024SoftDollarTiersProto\252\002\016IBApi.protobuf'
+ _globals['_SOFTDOLLARTIERS']._serialized_start=57
+ _globals['_SOFTDOLLARTIERS']._serialized_end=155
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/StartApiRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/StartApiRequest_pb2.py
new file mode 100644
index 00000000..d8c8e562
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/StartApiRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: StartApiRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'StartApiRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15StartApiRequest.proto\x12\x08protobuf\"q\n\x0fStartApiRequest\x12\x15\n\x08\x63lientId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12!\n\x14optionalCapabilities\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0b\n\t_clientIdB\x17\n\x15_optionalCapabilitiesB?\n\x16\x63om.ib.client.protobufB\x14StartApiRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'StartApiRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024StartApiRequestProto\252\002\016IBApi.protobuf'
+ _globals['_STARTAPIREQUEST']._serialized_start=35
+ _globals['_STARTAPIREQUEST']._serialized_end=148
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SubscribeToGroupEventsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SubscribeToGroupEventsRequest_pb2.py
new file mode 100644
index 00000000..cac4e8e5
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SubscribeToGroupEventsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SubscribeToGroupEventsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SubscribeToGroupEventsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n#SubscribeToGroupEventsRequest.proto\x12\x08protobuf\"_\n\x1dSubscribeToGroupEventsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07groupId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_groupIdBM\n\x16\x63om.ib.client.protobufB\"SubscribeToGroupEventsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SubscribeToGroupEventsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\"SubscribeToGroupEventsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_SUBSCRIBETOGROUPEVENTSREQUEST']._serialized_start=49
+ _globals['_SUBSCRIBETOGROUPEVENTSREQUEST']._serialized_end=144
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SymbolSamples_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SymbolSamples_pb2.py
new file mode 100644
index 00000000..897d4004
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/SymbolSamples_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: SymbolSamples.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'SymbolSamples.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.ContractDescription_pb2 as ContractDescription__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13SymbolSamples.proto\x12\x08protobuf\x1a\x19\x43ontractDescription.proto\"j\n\rSymbolSamples\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12;\n\x14\x63ontractDescriptions\x18\x02 \x03(\x0b\x32\x1d.protobuf.ContractDescriptionB\x08\n\x06_reqIdB=\n\x16\x63om.ib.client.protobufB\x12SymbolSamplesProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'SymbolSamples_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022SymbolSamplesProto\252\002\016IBApi.protobuf'
+ _globals['_SYMBOLSAMPLES']._serialized_start=60
+ _globals['_SYMBOLSAMPLES']._serialized_end=166
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickAttribBidAsk_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickAttribBidAsk_pb2.py
new file mode 100644
index 00000000..f49089c8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickAttribBidAsk_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickAttribBidAsk.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickAttribBidAsk.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16TickAttribBidAsk.proto\x12\x08protobuf\"d\n\x10TickAttribBidAsk\x12\x17\n\nbidPastLow\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x18\n\x0b\x61skPastHigh\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\r\n\x0b_bidPastLowB\x0e\n\x0c_askPastHighB@\n\x16\x63om.ib.client.protobufB\x15TickAttribBidAskProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickAttribBidAsk_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025TickAttribBidAskProto\252\002\016IBApi.protobuf'
+ _globals['_TICKATTRIBBIDASK']._serialized_start=36
+ _globals['_TICKATTRIBBIDASK']._serialized_end=136
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickAttribLast_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickAttribLast_pb2.py
new file mode 100644
index 00000000..74e14caa
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickAttribLast_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickAttribLast.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickAttribLast.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14TickAttribLast.proto\x12\x08protobuf\"^\n\x0eTickAttribLast\x12\x16\n\tpastLimit\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x17\n\nunreported\x18\x02 \x01(\x08H\x01\x88\x01\x01\x42\x0c\n\n_pastLimitB\r\n\x0b_unreportedB>\n\x16\x63om.ib.client.protobufB\x13TickAttribLastProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickAttribLast_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023TickAttribLastProto\252\002\016IBApi.protobuf'
+ _globals['_TICKATTRIBLAST']._serialized_start=34
+ _globals['_TICKATTRIBLAST']._serialized_end=128
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickByTickData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickByTickData_pb2.py
new file mode 100644
index 00000000..97c15d81
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickByTickData_pb2.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickByTickData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickByTickData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.HistoricalTickLast_pb2 as HistoricalTickLast__pb2
+import ibapi.protobuf.HistoricalTickBidAsk_pb2 as HistoricalTickBidAsk__pb2
+import ibapi.protobuf.HistoricalTick_pb2 as HistoricalTick__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14TickByTickData.proto\x12\x08protobuf\x1a\x18HistoricalTickLast.proto\x1a\x1aHistoricalTickBidAsk.proto\x1a\x14HistoricalTick.proto\"\x92\x02\n\x0eTickByTickData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x01\x88\x01\x01\x12\x15\n\x08tickType\x18\x02 \x01(\x05H\x02\x88\x01\x01\x12:\n\x12historicalTickLast\x18\x03 \x01(\x0b\x32\x1c.protobuf.HistoricalTickLastH\x00\x12>\n\x14historicalTickBidAsk\x18\x04 \x01(\x0b\x32\x1e.protobuf.HistoricalTickBidAskH\x00\x12:\n\x16historicalTickMidPoint\x18\x05 \x01(\x0b\x32\x18.protobuf.HistoricalTickH\x00\x42\x06\n\x04tickB\x08\n\x06_reqIdB\x0b\n\t_tickTypeB>\n\x16\x63om.ib.client.protobufB\x13TickByTickDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickByTickData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\023TickByTickDataProto\252\002\016IBApi.protobuf'
+ _globals['_TICKBYTICKDATA']._serialized_start=111
+ _globals['_TICKBYTICKDATA']._serialized_end=385
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickByTickRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickByTickRequest_pb2.py
new file mode 100644
index 00000000..042f6ee9
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickByTickRequest_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickByTickRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickByTickRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.Contract_pb2 as Contract__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17TickByTickRequest.proto\x12\x08protobuf\x1a\x0e\x43ontract.proto\"\xe3\x01\n\x11TickByTickRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12)\n\x08\x63ontract\x18\x02 \x01(\x0b\x32\x12.protobuf.ContractH\x01\x88\x01\x01\x12\x15\n\x08tickType\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rnumberOfTicks\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12\x17\n\nignoreSize\x18\x05 \x01(\x08H\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_contractB\x0b\n\t_tickTypeB\x10\n\x0e_numberOfTicksB\r\n\x0b_ignoreSizeBA\n\x16\x63om.ib.client.protobufB\x16TickByTickRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickByTickRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\026TickByTickRequestProto\252\002\016IBApi.protobuf'
+ _globals['_TICKBYTICKREQUEST']._serialized_start=54
+ _globals['_TICKBYTICKREQUEST']._serialized_end=281
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickGeneric_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickGeneric_pb2.py
new file mode 100644
index 00000000..7d6af842
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickGeneric_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickGeneric.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickGeneric.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11TickGeneric.proto\x12\x08protobuf\"m\n\x0bTickGeneric\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08tickType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05value\x18\x03 \x01(\x01H\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_tickTypeB\x08\n\x06_valueB;\n\x16\x63om.ib.client.protobufB\x10TickGenericProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickGeneric_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020TickGenericProto\252\002\016IBApi.protobuf'
+ _globals['_TICKGENERIC']._serialized_start=31
+ _globals['_TICKGENERIC']._serialized_end=140
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickNews_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickNews_pb2.py
new file mode 100644
index 00000000..a5e4f845
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickNews_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickNews.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickNews.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eTickNews.proto\x12\x08protobuf\"\xea\x01\n\x08TickNews\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\ttimestamp\x18\x02 \x01(\x03H\x01\x88\x01\x01\x12\x19\n\x0cproviderCode\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x16\n\tarticleId\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08headline\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x16\n\textraData\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\x08\n\x06_reqIdB\x0c\n\n_timestampB\x0f\n\r_providerCodeB\x0c\n\n_articleIdB\x0b\n\t_headlineB\x0c\n\n_extraDataB8\n\x16\x63om.ib.client.protobufB\rTickNewsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickNews_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\rTickNewsProto\252\002\016IBApi.protobuf'
+ _globals['_TICKNEWS']._serialized_start=29
+ _globals['_TICKNEWS']._serialized_end=263
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickOptionComputation_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickOptionComputation_pb2.py
new file mode 100644
index 00000000..c8d2967f
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickOptionComputation_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickOptionComputation.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickOptionComputation.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1bTickOptionComputation.proto\x12\x08protobuf\"\x8f\x03\n\x15TickOptionComputation\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08tickType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x17\n\ntickAttrib\x18\x03 \x01(\x05H\x02\x88\x01\x01\x12\x17\n\nimpliedVol\x18\x04 \x01(\x01H\x03\x88\x01\x01\x12\x12\n\x05\x64\x65lta\x18\x05 \x01(\x01H\x04\x88\x01\x01\x12\x15\n\x08optPrice\x18\x06 \x01(\x01H\x05\x88\x01\x01\x12\x17\n\npvDividend\x18\x07 \x01(\x01H\x06\x88\x01\x01\x12\x12\n\x05gamma\x18\x08 \x01(\x01H\x07\x88\x01\x01\x12\x11\n\x04vega\x18\t \x01(\x01H\x08\x88\x01\x01\x12\x12\n\x05theta\x18\n \x01(\x01H\t\x88\x01\x01\x12\x15\n\x08undPrice\x18\x0b \x01(\x01H\n\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_tickTypeB\r\n\x0b_tickAttribB\r\n\x0b_impliedVolB\x08\n\x06_deltaB\x0b\n\t_optPriceB\r\n\x0b_pvDividendB\x08\n\x06_gammaB\x07\n\x05_vegaB\x08\n\x06_thetaB\x0b\n\t_undPriceBE\n\x16\x63om.ib.client.protobufB\x1aTickOptionComputationProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickOptionComputation_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\032TickOptionComputationProto\252\002\016IBApi.protobuf'
+ _globals['_TICKOPTIONCOMPUTATION']._serialized_start=42
+ _globals['_TICKOPTIONCOMPUTATION']._serialized_end=441
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickPrice_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickPrice_pb2.py
new file mode 100644
index 00000000..6942bd65
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickPrice_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickPrice.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickPrice.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fTickPrice.proto\x12\x08protobuf\"\xab\x01\n\tTickPrice\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08tickType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05price\x18\x03 \x01(\x01H\x02\x88\x01\x01\x12\x11\n\x04size\x18\x04 \x01(\tH\x03\x88\x01\x01\x12\x15\n\x08\x61ttrMask\x18\x05 \x01(\x05H\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_tickTypeB\x08\n\x06_priceB\x07\n\x05_sizeB\x0b\n\t_attrMaskB9\n\x16\x63om.ib.client.protobufB\x0eTickPriceProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickPrice_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\016TickPriceProto\252\002\016IBApi.protobuf'
+ _globals['_TICKPRICE']._serialized_start=30
+ _globals['_TICKPRICE']._serialized_end=201
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickReqParams_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickReqParams_pb2.py
new file mode 100644
index 00000000..0210dd31
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickReqParams_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickReqParams.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickReqParams.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13TickReqParams.proto\x12\x08protobuf\"\xa1\x02\n\rTickReqParams\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x14\n\x07minTick\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x18\n\x0b\x62\x62oExchange\x18\x03 \x01(\tH\x02\x88\x01\x01\x12 \n\x13snapshotPermissions\x18\x04 \x01(\x05H\x03\x88\x01\x01\x12\x1f\n\x12lastPricePrecision\x18\x05 \x01(\tH\x04\x88\x01\x01\x12\x1e\n\x11lastSizePrecision\x18\x06 \x01(\tH\x05\x88\x01\x01\x42\x08\n\x06_reqIdB\n\n\x08_minTickB\x0e\n\x0c_bboExchangeB\x16\n\x14_snapshotPermissionsB\x15\n\x13_lastPricePrecisionB\x14\n\x12_lastSizePrecisionB=\n\x16\x63om.ib.client.protobufB\x12TickReqParamsProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickReqParams_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022TickReqParamsProto\252\002\016IBApi.protobuf'
+ _globals['_TICKREQPARAMS']._serialized_start=34
+ _globals['_TICKREQPARAMS']._serialized_end=323
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickSize_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickSize_pb2.py
new file mode 100644
index 00000000..07d964e8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickSize_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickSize.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickSize.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eTickSize.proto\x12\x08protobuf\"h\n\x08TickSize\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08tickType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x11\n\x04size\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_tickTypeB\x07\n\x05_sizeB8\n\x16\x63om.ib.client.protobufB\rTickSizeProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickSize_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\rTickSizeProto\252\002\016IBApi.protobuf'
+ _globals['_TICKSIZE']._serialized_start=28
+ _globals['_TICKSIZE']._serialized_end=132
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickSnapshotEnd_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickSnapshotEnd_pb2.py
new file mode 100644
index 00000000..86c842c3
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickSnapshotEnd_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickSnapshotEnd.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickSnapshotEnd.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15TickSnapshotEnd.proto\x12\x08protobuf\"/\n\x0fTickSnapshotEnd\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB?\n\x16\x63om.ib.client.protobufB\x14TickSnapshotEndProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickSnapshotEnd_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024TickSnapshotEndProto\252\002\016IBApi.protobuf'
+ _globals['_TICKSNAPSHOTEND']._serialized_start=35
+ _globals['_TICKSNAPSHOTEND']._serialized_end=82
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickString_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickString_pb2.py
new file mode 100644
index 00000000..ceeb4384
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/TickString_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: TickString.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'TickString.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x10TickString.proto\x12\x08protobuf\"l\n\nTickString\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08tickType\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x12\n\x05value\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_tickTypeB\x08\n\x06_valueB:\n\x16\x63om.ib.client.protobufB\x0fTickStringProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'TickString_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\017TickStringProto\252\002\016IBApi.protobuf'
+ _globals['_TICKSTRING']._serialized_start=30
+ _globals['_TICKSTRING']._serialized_end=138
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UnsubscribeFromGroupEventsRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UnsubscribeFromGroupEventsRequest_pb2.py
new file mode 100644
index 00000000..5dee18b1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UnsubscribeFromGroupEventsRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UnsubscribeFromGroupEventsRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UnsubscribeFromGroupEventsRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'UnsubscribeFromGroupEventsRequest.proto\x12\x08protobuf\"A\n!UnsubscribeFromGroupEventsRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBQ\n\x16\x63om.ib.client.protobufB&UnsubscribeFromGroupEventsRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UnsubscribeFromGroupEventsRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB&UnsubscribeFromGroupEventsRequestProto\252\002\016IBApi.protobuf'
+ _globals['_UNSUBSCRIBEFROMGROUPEVENTSREQUEST']._serialized_start=53
+ _globals['_UNSUBSCRIBEFROMGROUPEVENTSREQUEST']._serialized_end=118
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigRequest_pb2.py
new file mode 100644
index 00000000..9919bf06
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigRequest_pb2.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UpdateConfigRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UpdateConfigRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.LockAndExitConfig_pb2 as LockAndExitConfig__pb2
+import ibapi.protobuf.MessageConfig_pb2 as MessageConfig__pb2
+import ibapi.protobuf.ApiConfig_pb2 as ApiConfig__pb2
+import ibapi.protobuf.OrdersConfig_pb2 as OrdersConfig__pb2
+import ibapi.protobuf.UpdateConfigWarning_pb2 as UpdateConfigWarning__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19UpdateConfigRequest.proto\x12\x08protobuf\x1a\x17LockAndExitConfig.proto\x1a\x13MessageConfig.proto\x1a\x0f\x41piConfig.proto\x1a\x12OrdersConfig.proto\x1a\x19UpdateConfigWarning.proto\"\x83\x03\n\x13UpdateConfigRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x35\n\x0blockAndExit\x18\x02 \x01(\x0b\x32\x1b.protobuf.LockAndExitConfigH\x01\x88\x01\x01\x12)\n\x08messages\x18\x03 \x03(\x0b\x32\x17.protobuf.MessageConfig\x12%\n\x03\x61pi\x18\x04 \x01(\x0b\x32\x13.protobuf.ApiConfigH\x02\x88\x01\x01\x12+\n\x06orders\x18\x05 \x01(\x0b\x32\x16.protobuf.OrdersConfigH\x03\x88\x01\x01\x12\x37\n\x10\x61\x63\x63\x65ptedWarnings\x18\x06 \x03(\x0b\x32\x1d.protobuf.UpdateConfigWarning\x12\"\n\x15resetAPIOrderSequence\x18\x07 \x01(\x08H\x04\x88\x01\x01\x42\x08\n\x06_reqIdB\x0e\n\x0c_lockAndExitB\x06\n\x04_apiB\t\n\x07_ordersB\x18\n\x16_resetAPIOrderSequenceBC\n\x16\x63om.ib.client.protobufB\x18UpdateConfigRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UpdateConfigRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030UpdateConfigRequestProto\252\002\016IBApi.protobuf'
+ _globals['_UPDATECONFIGREQUEST']._serialized_start=150
+ _globals['_UPDATECONFIGREQUEST']._serialized_end=537
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigResponse_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigResponse_pb2.py
new file mode 100644
index 00000000..5f4fb8ea
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigResponse_pb2.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UpdateConfigResponse.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UpdateConfigResponse.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+import ibapi.protobuf.UpdateConfigWarning_pb2 as UpdateConfigWarning__pb2
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aUpdateConfigResponse.proto\x12\x08protobuf\x1a\x19UpdateConfigWarning.proto\"\xce\x01\n\x14UpdateConfigResponse\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x13\n\x06status\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07message\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x15\n\rchangedFields\x18\x04 \x03(\t\x12\x0e\n\x06\x65rrors\x18\x05 \x03(\t\x12/\n\x08warnings\x18\x06 \x03(\x0b\x32\x1d.protobuf.UpdateConfigWarningB\x08\n\x06_reqIdB\t\n\x07_statusB\n\n\x08_messageBD\n\x16\x63om.ib.client.protobufB\x19UpdateConfigResponseProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UpdateConfigResponse_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031UpdateConfigResponseProto\252\002\016IBApi.protobuf'
+ _globals['_UPDATECONFIGRESPONSE']._serialized_start=68
+ _globals['_UPDATECONFIGRESPONSE']._serialized_end=274
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigWarning_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigWarning_pb2.py
new file mode 100644
index 00000000..097ac9b3
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateConfigWarning_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UpdateConfigWarning.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UpdateConfigWarning.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19UpdateConfigWarning.proto\x12\x08protobuf\"{\n\x13UpdateConfigWarning\x12\x16\n\tmessageId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05title\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x14\n\x07message\x18\x03 \x01(\tH\x02\x88\x01\x01\x42\x0c\n\n_messageIdB\x08\n\x06_titleB\n\n\x08_messageBC\n\x16\x63om.ib.client.protobufB\x18UpdateConfigWarningProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UpdateConfigWarning_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030UpdateConfigWarningProto\252\002\016IBApi.protobuf'
+ _globals['_UPDATECONFIGWARNING']._serialized_start=39
+ _globals['_UPDATECONFIGWARNING']._serialized_end=162
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateDisplayGroupRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateDisplayGroupRequest_pb2.py
new file mode 100644
index 00000000..77a14260
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UpdateDisplayGroupRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UpdateDisplayGroupRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UpdateDisplayGroupRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fUpdateDisplayGroupRequest.proto\x12\x08protobuf\"e\n\x19UpdateDisplayGroupRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x19\n\x0c\x63ontractInfo\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0f\n\r_contractInfoBI\n\x16\x63om.ib.client.protobufB\x1eUpdateDisplayGroupRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UpdateDisplayGroupRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\036UpdateDisplayGroupRequestProto\252\002\016IBApi.protobuf'
+ _globals['_UPDATEDISPLAYGROUPREQUEST']._serialized_start=45
+ _globals['_UPDATEDISPLAYGROUPREQUEST']._serialized_end=146
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UserInfoRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UserInfoRequest_pb2.py
new file mode 100644
index 00000000..4563a4df
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UserInfoRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UserInfoRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UserInfoRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15UserInfoRequest.proto\x12\x08protobuf\"/\n\x0fUserInfoRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdB?\n\x16\x63om.ib.client.protobufB\x14UserInfoRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UserInfoRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024UserInfoRequestProto\252\002\016IBApi.protobuf'
+ _globals['_USERINFOREQUEST']._serialized_start=35
+ _globals['_USERINFOREQUEST']._serialized_end=82
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UserInfo_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UserInfo_pb2.py
new file mode 100644
index 00000000..00a9502a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/UserInfo_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: UserInfo.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'UserInfo.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0eUserInfo.proto\x12\x08protobuf\"Z\n\x08UserInfo\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x1c\n\x0fwhiteBrandingId\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x12\n\x10_whiteBrandingIdB8\n\x16\x63om.ib.client.protobufB\rUserInfoProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'UserInfo_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\rUserInfoProto\252\002\016IBApi.protobuf'
+ _globals['_USERINFO']._serialized_start=28
+ _globals['_USERINFO']._serialized_end=118
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyCompleted_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyCompleted_pb2.py
new file mode 100644
index 00000000..2215183b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyCompleted_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: VerifyCompleted.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'VerifyCompleted.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15VerifyCompleted.proto\x12\x08protobuf\"c\n\x0fVerifyCompleted\x12\x19\n\x0cisSuccessful\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x16\n\terrorText\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x0f\n\r_isSuccessfulB\x0c\n\n_errorTextB?\n\x16\x63om.ib.client.protobufB\x14VerifyCompletedProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'VerifyCompleted_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\024VerifyCompletedProto\252\002\016IBApi.protobuf'
+ _globals['_VERIFYCOMPLETED']._serialized_start=35
+ _globals['_VERIFYCOMPLETED']._serialized_end=134
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyMessageApi_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyMessageApi_pb2.py
new file mode 100644
index 00000000..399e69ac
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyMessageApi_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: VerifyMessageApi.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'VerifyMessageApi.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x16VerifyMessageApi.proto\x12\x08protobuf\"4\n\x10VerifyMessageApi\x12\x14\n\x07\x61piData\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_apiDataB@\n\x16\x63om.ib.client.protobufB\x15VerifyMessageApiProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'VerifyMessageApi_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\025VerifyMessageApiProto\252\002\016IBApi.protobuf'
+ _globals['_VERIFYMESSAGEAPI']._serialized_start=36
+ _globals['_VERIFYMESSAGEAPI']._serialized_end=88
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyMessageRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyMessageRequest_pb2.py
new file mode 100644
index 00000000..2a2e67ad
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyMessageRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: VerifyMessageRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'VerifyMessageRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1aVerifyMessageRequest.proto\x12\x08protobuf\"8\n\x14VerifyMessageRequest\x12\x14\n\x07\x61piData\x18\x01 \x01(\tH\x00\x88\x01\x01\x42\n\n\x08_apiDataBD\n\x16\x63om.ib.client.protobufB\x19VerifyMessageRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'VerifyMessageRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\031VerifyMessageRequestProto\252\002\016IBApi.protobuf'
+ _globals['_VERIFYMESSAGEREQUEST']._serialized_start=40
+ _globals['_VERIFYMESSAGEREQUEST']._serialized_end=96
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyRequest_pb2.py
new file mode 100644
index 00000000..d076ac4d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/VerifyRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: VerifyRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'VerifyRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x13VerifyRequest.proto\x12\x08protobuf\"Y\n\rVerifyRequest\x12\x14\n\x07\x61piName\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x17\n\napiVersion\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\n\n\x08_apiNameB\r\n\x0b_apiVersionB=\n\x16\x63om.ib.client.protobufB\x12VerifyRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'VerifyRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\022VerifyRequestProto\252\002\016IBApi.protobuf'
+ _globals['_VERIFYREQUEST']._serialized_start=33
+ _globals['_VERIFYREQUEST']._serialized_end=122
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshEventDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshEventDataRequest_pb2.py
new file mode 100644
index 00000000..ba3927f1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshEventDataRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: WshEventDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'WshEventDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19WshEventDataRequest.proto\x12\x08protobuf\"\xef\x02\n\x13WshEventDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x12\n\x05\x63onId\x18\x02 \x01(\x05H\x01\x88\x01\x01\x12\x13\n\x06\x66ilter\x18\x03 \x01(\tH\x02\x88\x01\x01\x12\x1a\n\rfillWatchlist\x18\x04 \x01(\x08H\x03\x88\x01\x01\x12\x1a\n\rfillPortfolio\x18\x05 \x01(\x08H\x04\x88\x01\x01\x12\x1c\n\x0f\x66illCompetitors\x18\x06 \x01(\x08H\x05\x88\x01\x01\x12\x16\n\tstartDate\x18\x07 \x01(\tH\x06\x88\x01\x01\x12\x14\n\x07\x65ndDate\x18\x08 \x01(\tH\x07\x88\x01\x01\x12\x17\n\ntotalLimit\x18\t \x01(\x05H\x08\x88\x01\x01\x42\x08\n\x06_reqIdB\x08\n\x06_conIdB\t\n\x07_filterB\x10\n\x0e_fillWatchlistB\x10\n\x0e_fillPortfolioB\x12\n\x10_fillCompetitorsB\x0c\n\n_startDateB\n\n\x08_endDateB\r\n\x0b_totalLimitBC\n\x16\x63om.ib.client.protobufB\x18WshEventDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'WshEventDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\030WshEventDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_WSHEVENTDATAREQUEST']._serialized_start=40
+ _globals['_WSHEVENTDATAREQUEST']._serialized_end=407
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshEventData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshEventData_pb2.py
new file mode 100644
index 00000000..4d5df991
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshEventData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: WshEventData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'WshEventData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12WshEventData.proto\x12\x08protobuf\"P\n\x0cWshEventData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x64\x61taJson\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_dataJsonB<\n\x16\x63om.ib.client.protobufB\x11WshEventDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'WshEventData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\021WshEventDataProto\252\002\016IBApi.protobuf'
+ _globals['_WSHEVENTDATA']._serialized_start=32
+ _globals['_WSHEVENTDATA']._serialized_end=112
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshMetaDataRequest_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshMetaDataRequest_pb2.py
new file mode 100644
index 00000000..f707836a
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshMetaDataRequest_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: WshMetaDataRequest.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'WshMetaDataRequest.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x18WshMetaDataRequest.proto\x12\x08protobuf\"2\n\x12WshMetaDataRequest\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x42\x08\n\x06_reqIdBB\n\x16\x63om.ib.client.protobufB\x17WshMetaDataRequestProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'WshMetaDataRequest_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\027WshMetaDataRequestProto\252\002\016IBApi.protobuf'
+ _globals['_WSHMETADATAREQUEST']._serialized_start=38
+ _globals['_WSHMETADATAREQUEST']._serialized_end=88
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshMetaData_pb2.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshMetaData_pb2.py
new file mode 100644
index 00000000..a82bbf36
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/WshMetaData_pb2.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# NO CHECKED-IN PROTOBUF GENCODE
+# source: WshMetaData.proto
+# Protobuf Python Version: 5.29.5
+"""Generated protocol buffer code."""
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import descriptor_pool as _descriptor_pool
+from google.protobuf import runtime_version as _runtime_version
+from google.protobuf import symbol_database as _symbol_database
+from google.protobuf.internal import builder as _builder
+_runtime_version.ValidateProtobufRuntimeVersion(
+ _runtime_version.Domain.PUBLIC,
+ 5,
+ 29,
+ 5,
+ '',
+ 'WshMetaData.proto'
+)
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11WshMetaData.proto\x12\x08protobuf\"O\n\x0bWshMetaData\x12\x12\n\x05reqId\x18\x01 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x64\x61taJson\x18\x02 \x01(\tH\x01\x88\x01\x01\x42\x08\n\x06_reqIdB\x0b\n\t_dataJsonB;\n\x16\x63om.ib.client.protobufB\x10WshMetaDataProto\xaa\x02\x0eIBApi.protobufb\x06proto3')
+
+_globals = globals()
+_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
+_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'WshMetaData_pb2', _globals)
+if not _descriptor._USE_C_DESCRIPTORS:
+ _globals['DESCRIPTOR']._loaded_options = None
+ _globals['DESCRIPTOR']._serialized_options = b'\n\026com.ib.client.protobufB\020WshMetaDataProto\252\002\016IBApi.protobuf'
+ _globals['_WSHMETADATA']._serialized_start=31
+ _globals['_WSHMETADATA']._serialized_end=110
+# @@protoc_insertion_point(module_scope)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/__init__.py b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/__init__.py
new file mode 100644
index 00000000..f83d8a28
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/protobuf/__init__.py
@@ -0,0 +1 @@
+""" Package includes the Python API protocol buffers generated files for the TWS/IB Gateway """
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/reader.py b/packages/ibkr/ref/source/pythonclient/ibapi/reader.py
new file mode 100644
index 00000000..0167b05d
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/reader.py
@@ -0,0 +1,49 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+
+The EReader runs in a separate threads and is responsible for receiving the
+incoming messages.
+It will read the packets from the wire, use the low level IB messaging to
+remove the size prefix and put the rest in a Queue.
+"""
+
+import logging
+from threading import Thread
+
+from ibapi import comm
+
+logger = logging.getLogger(__name__)
+
+
+class EReader(Thread):
+ def __init__(self, conn, msg_queue):
+ super().__init__()
+ self.conn = conn
+ self.msg_queue = msg_queue
+
+ def run(self):
+ try:
+ logger.debug("EReader thread started")
+ buf = b""
+ while self.conn.isConnected():
+ data = self.conn.recvMsg()
+ logger.debug("reader loop, recvd size %d", len(data))
+ buf += data
+
+ while len(buf) > 0:
+ (size, msg, buf) = comm.read_msg(buf)
+ # logger.debug("resp %s", buf.decode('ascii'))
+ logger.debug(
+ "size:%d msg.size:%d msg:|%s| buf:%s|", size, len(msg), buf, "|"
+ )
+
+ if msg:
+ self.msg_queue.put(msg)
+ else:
+ logger.debug("more incoming packet(s) are needed ")
+ break
+
+ logger.debug("EReader thread finished")
+ except:
+ logger.exception("unhandled exception in EReader thread")
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/scanner.py b/packages/ibkr/ref/source/pythonclient/ibapi/scanner.py
new file mode 100644
index 00000000..d5fad82b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/scanner.py
@@ -0,0 +1,80 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+
+from ibapi.object_implem import Object
+from ibapi.const import UNSET_INTEGER, UNSET_DOUBLE
+
+
+class ScanData(Object):
+ def __init__(
+ self,
+ contract=None,
+ rank=0,
+ distance="",
+ benchmark="",
+ projection="",
+ legsStr="",
+ marketName="",
+ ):
+ self.contract = contract
+ self.rank = rank
+ self.distance = distance
+ self.benchmark = benchmark
+ self.projection = projection
+ self.legsStr = legsStr
+ self.marketName = marketName
+
+ def __str__(self):
+ return (
+ "Rank: %d, Symbol: %s, SecType: %s, Currency: %s, Distance: %s, Benchmark: %s, Projection: %s, Legs String: %s, MarketName: %s"
+ % (
+ self.rank,
+ self.contract.symbol,
+ self.contract.secType,
+ self.contract.currency,
+ self.distance,
+ self.benchmark,
+ self.projection,
+ self.legsStr,
+ self.marketName
+ )
+ )
+
+
+NO_ROW_NUMBER_SPECIFIED = -1
+
+
+class ScannerSubscription(Object):
+ def __init__(self):
+ self.numberOfRows = NO_ROW_NUMBER_SPECIFIED
+ self.instrument = ""
+ self.locationCode = ""
+ self.scanCode = ""
+ self.abovePrice = UNSET_DOUBLE
+ self.belowPrice = UNSET_DOUBLE
+ self.aboveVolume = UNSET_INTEGER
+ self.marketCapAbove = UNSET_DOUBLE
+ self.marketCapBelow = UNSET_DOUBLE
+ self.moodyRatingAbove = ""
+ self.moodyRatingBelow = ""
+ self.spRatingAbove = ""
+ self.spRatingBelow = ""
+ self.maturityDateAbove = ""
+ self.maturityDateBelow = ""
+ self.couponRateAbove = UNSET_DOUBLE
+ self.couponRateBelow = UNSET_DOUBLE
+ self.excludeConvertible = False
+ self.averageOptionVolumeAbove = UNSET_INTEGER
+ self.scannerSettingPairs = ""
+ self.stockTypeFilter = ""
+
+ def __str__(self):
+ s = "Instrument: %s, LocationCode: %s, ScanCode: %s" % (
+ self.instrument,
+ self.locationCode,
+ self.scanCode,
+ )
+ return s
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/server_versions.py b/packages/ibkr/ref/source/pythonclient/ibapi/server_versions.py
new file mode 100644
index 00000000..d991bb21
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/server_versions.py
@@ -0,0 +1,178 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+"""
+The known server versions.
+"""
+
+# MIN_SERVER_VER_REAL_TIME_BARS = 34
+# MIN_SERVER_VER_SCALE_ORDERS = 35
+# MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35
+# MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35
+# MIN_SERVER_VER_WHAT_IF_ORDERS = 36
+# MIN_SERVER_VER_CONTRACT_CONID = 37
+MIN_SERVER_VER_PTA_ORDERS = 39
+MIN_SERVER_VER_FUNDAMENTAL_DATA = 40
+MIN_SERVER_VER_DELTA_NEUTRAL = 40
+MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40
+MIN_SERVER_VER_SCALE_ORDERS2 = 40
+MIN_SERVER_VER_ALGO_ORDERS = 41
+MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42
+MIN_SERVER_VER_NOT_HELD = 44
+MIN_SERVER_VER_SEC_ID_TYPE = 45
+MIN_SERVER_VER_PLACE_ORDER_CONID = 46
+MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47
+MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49
+MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50
+MIN_SERVER_VER_SSHORTX_OLD = 51
+MIN_SERVER_VER_SSHORTX = 52
+MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53
+MIN_SERVER_VER_HEDGE_ORDERS = 54
+MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55
+MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56
+MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57
+MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58
+MIN_SERVER_VER_SCALE_ORDERS3 = 60
+MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE = 61
+MIN_SERVER_VER_TRAILING_PERCENT = 62
+MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE = 66
+MIN_SERVER_VER_POSITIONS = 67
+MIN_SERVER_VER_ACCOUNT_SUMMARY = 67
+MIN_SERVER_VER_TRADING_CLASS = 68
+MIN_SERVER_VER_SCALE_TABLE = 69
+MIN_SERVER_VER_LINKING = 70
+MIN_SERVER_VER_ALGO_ID = 71
+MIN_SERVER_VER_OPTIONAL_CAPABILITIES = 72
+MIN_SERVER_VER_ORDER_SOLICITED = 73
+MIN_SERVER_VER_LINKING_AUTH = 74
+MIN_SERVER_VER_PRIMARYEXCH = 75
+MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE = 76
+MIN_SERVER_VER_FRACTIONAL_POSITIONS = 101
+MIN_SERVER_VER_PEGGED_TO_BENCHMARK = 102
+MIN_SERVER_VER_MODELS_SUPPORT = 103
+MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ = 104
+MIN_SERVER_VER_EXT_OPERATOR = 105
+MIN_SERVER_VER_SOFT_DOLLAR_TIER = 106
+MIN_SERVER_VER_REQ_FAMILY_CODES = 107
+MIN_SERVER_VER_REQ_MATCHING_SYMBOLS = 108
+MIN_SERVER_VER_PAST_LIMIT = 109
+MIN_SERVER_VER_MD_SIZE_MULTIPLIER = 110
+MIN_SERVER_VER_CASH_QTY = 111
+MIN_SERVER_VER_REQ_MKT_DEPTH_EXCHANGES = 112
+MIN_SERVER_VER_TICK_NEWS = 113
+MIN_SERVER_VER_REQ_SMART_COMPONENTS = 114
+MIN_SERVER_VER_REQ_NEWS_PROVIDERS = 115
+MIN_SERVER_VER_REQ_NEWS_ARTICLE = 116
+MIN_SERVER_VER_REQ_HISTORICAL_NEWS = 117
+MIN_SERVER_VER_REQ_HEAD_TIMESTAMP = 118
+MIN_SERVER_VER_REQ_HISTOGRAM = 119
+MIN_SERVER_VER_SERVICE_DATA_TYPE = 120
+MIN_SERVER_VER_AGG_GROUP = 121
+MIN_SERVER_VER_UNDERLYING_INFO = 122
+MIN_SERVER_VER_CANCEL_HEADTIMESTAMP = 123
+MIN_SERVER_VER_SYNT_REALTIME_BARS = 124
+MIN_SERVER_VER_CFD_REROUTE = 125
+MIN_SERVER_VER_MARKET_RULES = 126
+MIN_SERVER_VER_PNL = 127
+MIN_SERVER_VER_NEWS_QUERY_ORIGINS = 128
+MIN_SERVER_VER_UNREALIZED_PNL = 129
+MIN_SERVER_VER_HISTORICAL_TICKS = 130
+MIN_SERVER_VER_MARKET_CAP_PRICE = 131
+MIN_SERVER_VER_PRE_OPEN_BID_ASK = 132
+MIN_SERVER_VER_REAL_EXPIRATION_DATE = 134
+MIN_SERVER_VER_REALIZED_PNL = 135
+MIN_SERVER_VER_LAST_LIQUIDITY = 136
+MIN_SERVER_VER_TICK_BY_TICK = 137
+MIN_SERVER_VER_DECISION_MAKER = 138
+MIN_SERVER_VER_MIFID_EXECUTION = 139
+MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE = 140
+MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE = 141
+MIN_SERVER_VER_WHAT_IF_EXT_FIELDS = 142
+MIN_SERVER_VER_SCANNER_GENERIC_OPTS = 143
+MIN_SERVER_VER_API_BIND_ORDER = 144
+MIN_SERVER_VER_ORDER_CONTAINER = 145
+MIN_SERVER_VER_SMART_DEPTH = 146
+MIN_SERVER_VER_REMOVE_NULL_ALL_CASTING = 147
+MIN_SERVER_VER_D_PEG_ORDERS = 148
+MIN_SERVER_VER_MKT_DEPTH_PRIM_EXCHANGE = 149
+MIN_SERVER_VER_COMPLETED_ORDERS = 150
+MIN_SERVER_VER_PRICE_MGMT_ALGO = 151
+MIN_SERVER_VER_STOCK_TYPE = 152
+MIN_SERVER_VER_ENCODE_MSG_ASCII7 = 153
+MIN_SERVER_VER_SEND_ALL_FAMILY_CODES = 154
+MIN_SERVER_VER_NO_DEFAULT_OPEN_CLOSE = 155
+MIN_SERVER_VER_PRICE_BASED_VOLATILITY = 156
+MIN_SERVER_VER_REPLACE_FA_END = 157
+MIN_SERVER_VER_DURATION = 158
+MIN_SERVER_VER_MARKET_DATA_IN_SHARES = 159
+MIN_SERVER_VER_POST_TO_ATS = 160
+MIN_SERVER_VER_WSHE_CALENDAR = 161
+MIN_SERVER_VER_AUTO_CANCEL_PARENT = 162
+MIN_SERVER_VER_FRACTIONAL_SIZE_SUPPORT = 163
+MIN_SERVER_VER_SIZE_RULES = 164
+MIN_SERVER_VER_HISTORICAL_SCHEDULE = 165
+MIN_SERVER_VER_ADVANCED_ORDER_REJECT = 166
+MIN_SERVER_VER_USER_INFO = 167
+MIN_SERVER_VER_CRYPTO_AGGREGATED_TRADES = 168
+MIN_SERVER_VER_MANUAL_ORDER_TIME = 169
+MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS = 170
+MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS = 171
+MIN_SERVER_VER_IPO_PRICES = 172
+MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE = 173
+MIN_SERVER_VER_INSTRUMENT_TIMEZONE = 174
+MIN_SERVER_VER_HMDS_MARKET_DATA_IN_SHARES = 175
+MIN_SERVER_VER_BOND_ISSUERID = 176
+MIN_SERVER_VER_FA_PROFILE_DESUPPORT = 177
+MIN_SERVER_VER_PENDING_PRICE_REVISION = 178
+MIN_SERVER_VER_FUND_DATA_FIELDS = 179
+MIN_SERVER_VER_MANUAL_ORDER_TIME_EXERCISE_OPTIONS = 180
+MIN_SERVER_VER_OPEN_ORDER_AD_STRATEGY = 181
+MIN_SERVER_VER_LAST_TRADE_DATE = 182
+MIN_SERVER_VER_CUSTOMER_ACCOUNT = 183
+MIN_SERVER_VER_PROFESSIONAL_CUSTOMER = 184
+MIN_SERVER_VER_BOND_ACCRUED_INTEREST = 185
+MIN_SERVER_VER_INELIGIBILITY_REASONS = 186
+MIN_SERVER_VER_RFQ_FIELDS = 187
+MIN_SERVER_VER_BOND_TRADING_HOURS = 188
+MIN_SERVER_VER_INCLUDE_OVERNIGHT = 189
+MIN_SERVER_VER_UNDO_RFQ_FIELDS = 190
+MIN_SERVER_VER_PERM_ID_AS_LONG = 191
+MIN_SERVER_VER_CME_TAGGING_FIELDS = 192
+MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER = 193
+MIN_SERVER_VER_ERROR_TIME = 194
+MIN_SERVER_VER_FULL_ORDER_PREVIEW_FIELDS = 195
+MIN_SERVER_VER_HISTORICAL_DATA_END = 196
+MIN_SERVER_VER_CURRENT_TIME_IN_MILLIS = 197
+MIN_SERVER_VER_SUBMITTER = 198
+MIN_SERVER_VER_IMBALANCE_ONLY = 199
+MIN_SERVER_VER_PARAMETRIZED_DAYS_OF_EXECUTIONS = 200
+MIN_SERVER_VER_PROTOBUF = 201
+MIN_SERVER_VER_ZERO_STRIKE = 202
+MIN_SERVER_VER_PROTOBUF_PLACE_ORDER = 203
+MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER = 204
+MIN_SERVER_VER_PROTOBUF_CONTRACT_DATA = 205
+MIN_SERVER_VER_PROTOBUF_MARKET_DATA = 206
+MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS = 207
+MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA = 208
+MIN_SERVER_VER_PROTOBUF_NEWS_DATA = 209
+MIN_SERVER_VER_PROTOBUF_SCAN_DATA = 210
+MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1 = 211
+MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2 = 212
+MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3 = 213
+MIN_SERVER_VER_ADD_Z_SUFFIX_TO_UTC_DATE_TIME = 214
+MIN_SERVER_VER_CANCEL_CONTRACT_DATA = 215
+MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_1 = 216
+MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_2 = 217
+MIN_SERVER_VER_ATTACHED_ORDERS = 218
+MIN_SERVER_VER_CONFIG = 219
+MIN_SERVER_VER_MARKET_DATA_VOLUMES_IN_SHARES = 220
+MIN_SERVER_VER_UPDATE_CONFIG = 221
+MIN_SERVER_VER_FRACTIONAL_LAST_SIZE = 222
+
+# 100+ messaging */
+# 100 = enhanced handshake, msg length prefixes
+
+MIN_CLIENT_VER = 100
+MAX_CLIENT_VER = MIN_SERVER_VER_FRACTIONAL_LAST_SIZE
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/softdollartier.py b/packages/ibkr/ref/source/pythonclient/ibapi/softdollartier.py
new file mode 100644
index 00000000..e1d8b37b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/softdollartier.py
@@ -0,0 +1,16 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.object_implem import Object
+
+
+class SoftDollarTier(Object):
+ def __init__(self, name="", val="", displayName=""):
+ self.name = name
+ self.val = val
+ self.displayName = displayName
+
+ def __str__(self):
+ return f"Name: {self.name}, Value: {self.val}, DisplayName: {self.displayName}"
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/sync_wrapper.py b/packages/ibkr/ref/source/pythonclient/ibapi/sync_wrapper.py
new file mode 100644
index 00000000..8ff6926b
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/sync_wrapper.py
@@ -0,0 +1,683 @@
+'''
+2002-2025: Use is subject to Interactive Brokers TWS API Non-Commercial License ("License") terms.
+This License is NOT for anybody who is developing software applications that they wish to: (a) sell to third
+party users for a fee, or (b) give to third party users to generate an indirect financial benefit (e.g.,
+commissions). If You wish to make a software application for the purposes described in the preceding
+sentence then please contact Interactive Brokers
+'''
+# Synchronous Wrapper for TWS Python API
+
+"""
+Synchronous wrapper for Interactive Brokers TWS Python API.
+This wrapper simplifies the asynchronous nature of the original API by allowing
+synchronous calls that wait for responses before returning.
+"""
+
+import threading
+import time
+from decimal import Decimal
+from ibapi.account_summary_tags import AccountSummaryTags
+from ibapi.client import EClient
+from ibapi.wrapper import EWrapper
+from ibapi.contract import Contract, ContractDetails
+from ibapi.order import Order
+from ibapi.order_state import OrderState
+from ibapi.execution import Execution, ExecutionFilter
+from ibapi.order_cancel import OrderCancel
+from ibapi.common import TickerId, OrderId, BarData
+from ibapi.ticktype import TickTypeEnum
+
+class ResponseTimeout(Exception):
+ """Exception raised when a response is not received within the timeout period."""
+ pass
+
+class TWSSyncWrapper(EWrapper, EClient):
+ """
+ Synchronous wrapper for the TWS API that combines EWrapper and EClient
+ and provides synchronous methods to interact with TWS.
+ """
+
+ def __init__(self, timeout=30):
+ """
+ Initialize the wrapper with a default timeout for synchronous operations.
+
+ Args:
+ timeout: Default timeout in seconds for synchronous operations.
+ """
+ EWrapper.__init__(self)
+ EClient.__init__(self, wrapper=self)
+
+ # Default timeout for synchronous operations
+ self.timeout = timeout
+
+ # Synchronization primitives
+ self.response_events = {}
+ self.response_data = {}
+
+ # For storing responses
+ self.contract_details = {}
+ self.order_status = {}
+ self.open_orders = {}
+ self.executions = {}
+ self.portfolio = []
+ self.positions = {}
+ self.account_summary = {}
+ self.market_data = {}
+ self.historical_data = {}
+ self.current_time_value = None
+ self.next_valid_id_value = None
+ self.completion_events = {}
+ self.errors = {}
+
+ def connect_and_start(self, host, port, client_id):
+ """
+ Connect to TWS and start the message processing thread.
+
+ Args:
+ host: TWS host, usually '127.0.0.1'
+ port: TWS port, usually 7496 for TWS or 4001 for IB Gateway
+ client_id: A unique client ID
+
+ Returns:
+ True if connection is successful, False otherwise
+ """
+ self.connect(host, port, client_id)
+
+ # Wait for connection to be established
+ timeout = time.time() + 5 # 5 seconds timeout
+ while not self.isConnected() and time.time() < timeout:
+ time.sleep(0.1)
+
+ if not self.isConnected():
+ return False
+
+ # Create a thread for message processing
+ self.api_thread = threading.Thread(target=self.run)
+ self.api_thread.daemon = True
+ self.api_thread.start()
+
+ # Wait for connection to be fully established (i.e. next_valid_id is received)
+ timeout = time.time() + 5 # 5 seconds timeout
+ while self.next_valid_id_value is None and time.time() < timeout:
+ time.sleep(0.1)
+
+ if self.next_valid_id_value is None:
+ return False
+
+ return self.isConnected()
+
+ def _wait_for_response(self, req_id, event_name, timeout=None):
+ """
+ Wait for a response from TWS for a specific request.
+
+ Args:
+ req_id: The request ID to wait for
+ event_name: The event name to wait for
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ The response data
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ if timeout is None:
+ timeout = self.timeout
+
+ event_key = f"{event_name}_{req_id}"
+
+ # Create event if it doesn't exist
+ if event_key not in self.response_events:
+ self.response_events[event_key] = threading.Event()
+
+ # Wait for the event to be set
+ if not self.response_events[event_key].wait(timeout):
+ # Clean up
+ if event_key in self.response_events:
+ del self.response_events[event_key]
+ if event_key in self.response_data:
+ del self.response_data[event_key]
+ raise ResponseTimeout(f"No response received for {event_name} request {req_id} within {timeout} seconds")
+
+ # Get the response data
+ response = self.response_data.get(event_key)
+
+ # Clean up
+ if event_key in self.response_events:
+ del self.response_events[event_key]
+ if event_key in self.response_data:
+ del self.response_data[event_key]
+
+ return response
+
+ def _set_event(self, req_id, event_name, data=None):
+ """
+ Set an event to indicate that a response has been received.
+
+ Args:
+ req_id: The request ID
+ event_name: The event name
+ data: The response data
+ """
+ event_key = f"{event_name}_{req_id}"
+ self.response_data[event_key] = data
+
+ if event_key in self.response_events:
+ self.response_events[event_key].set()
+
+ # EWrapper method overrides
+ def nextValidId(self, orderId: int):
+ """Called by TWS with the next valid order ID."""
+ self.next_valid_id_value = orderId
+ self._set_event(0, "next_valid_id", orderId)
+ super().nextValidId(orderId)
+
+ def error(self, reqId: TickerId, errorTime: int, errorCode: int, errorString: str, advancedOrderRejectJson=""):
+ """Called when TWS returns an error message."""
+ error_info = {
+ "reqId": reqId,
+ "errorTime": errorTime,
+ "errorCode": errorCode,
+ "errorString": errorString,
+ "advancedOrderRejectJson": advancedOrderRejectJson
+ }
+
+ if reqId not in self.errors:
+ self.errors[reqId] = []
+ self.errors[reqId].append(error_info)
+
+ # Set event for any waiting synchronous calls
+ self._set_event(reqId, "error", error_info)
+
+ super().error(reqId, errorTime, errorCode, errorString, advancedOrderRejectJson)
+
+ def currentTime(self, time_value: int):
+ """Called with the current system time on the server side."""
+ self.current_time_value = time_value
+ self._set_event(0, "current_time", time_value)
+ super().currentTime(time_value)
+
+ def contractDetails(self, reqId: int, contractDetails: ContractDetails):
+ """Called with contract details."""
+ if reqId not in self.contract_details:
+ self.contract_details[reqId] = []
+ self.contract_details[reqId].append(contractDetails)
+ super().contractDetails(reqId, contractDetails)
+
+ def contractDetailsEnd(self, reqId: int):
+ """Called when all contract details have been received."""
+ self._set_event(reqId, "contract_details", self.contract_details.get(reqId, []))
+ super().contractDetailsEnd(reqId)
+
+ def orderStatus(self, orderId: OrderId, status: str, filled: Decimal, remaining: Decimal,avgFillPrice: float, permId: int, parentId: int, lastFillPrice: float, clientId: int, whyHeld: str, mktCapPrice: float):
+ """Called when the status of an order changes."""
+ order_status_data = {
+ "orderId": orderId,
+ "status": status,
+ "filled": filled,
+ "remaining": remaining,
+ "avgFillPrice": avgFillPrice,
+ "permId": permId,
+ "parentId": parentId,
+ "lastFillPrice": lastFillPrice,
+ "clientId": clientId,
+ "whyHeld": whyHeld,
+ "mktCapPrice": mktCapPrice
+ }
+
+ self.order_status[orderId] = order_status_data
+ self._set_event(orderId, "order_status", order_status_data)
+ super().orderStatus(orderId, status, filled, remaining, avgFillPrice, permId, parentId,lastFillPrice, clientId, whyHeld, mktCapPrice)
+
+ def openOrder(self, orderId: OrderId, contract: Contract, order: Order, orderState: OrderState):
+ """Called when an open order is returned."""
+ open_order_data = {
+ "orderId": orderId,
+ "contract": contract,
+ "order": order,
+ "orderState": orderState
+ }
+
+ self.open_orders[orderId] = open_order_data
+ super().openOrder(orderId, contract, order, orderState)
+
+ def openOrderEnd(self):
+ """Called at the end of a request for open orders."""
+ self._set_event(0, "open_orders", self.open_orders)
+ super().openOrderEnd()
+
+ def execDetails(self, reqId: int, contract: Contract, execution: Execution):
+ """Called when execution details are received."""
+ if reqId not in self.executions:
+ self.executions[reqId] = []
+
+ self.executions[reqId].append({
+ "contract": contract,
+ "execution": execution
+ })
+
+ super().execDetails(reqId, contract, execution)
+
+ def execDetailsEnd(self, reqId: int):
+ """Called when all execution details have been received."""
+ self._set_event(reqId, "executions", self.executions.get(reqId, []))
+ super().execDetailsEnd(reqId)
+
+ def updatePortfolio(self, contract: Contract, position: Decimal, marketPrice: float, marketValue: float, averageCost: float, unrealizedPNL: float, realizedPNL: float, accountName: str):
+ """Called when portfolio data is updated."""
+ portfolio_item = {
+ "contract": contract,
+ "position": position,
+ "marketPrice": marketPrice,
+ "marketValue": marketValue,
+ "averageCost": averageCost,
+ "unrealizedPNL": unrealizedPNL,
+ "realizedPNL": realizedPNL,
+ "accountName": accountName
+ }
+
+ self.portfolio.append(portfolio_item)
+ super().updatePortfolio(contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName)
+
+ def accountDownloadEnd(self, accountName: str):
+ """Called when account download has finished."""
+ self._set_event(0, "portfolio", self.portfolio)
+ super().accountDownloadEnd(accountName)
+
+ def position(self, account: str, contract: Contract, position: Decimal, avgCost: float):
+ """Called when position data is returned."""
+ if account not in self.positions:
+ self.positions[account] = []
+
+ self.positions[account].append({
+ "contract": contract,
+ "position": position,
+ "avgCost": avgCost
+ })
+
+ super().position(account, contract, position, avgCost)
+
+ def positionEnd(self):
+ """Called when all position data has been received."""
+ self._set_event(0, "positions", self.positions)
+ super().positionEnd()
+
+ def accountSummary(self, reqId: int, account: str, tag: str, value: str, currency: str):
+ """Called when account summary data is returned."""
+ if reqId not in self.account_summary:
+ self.account_summary[reqId] = {}
+
+ if account not in self.account_summary[reqId]:
+ self.account_summary[reqId][account] = {}
+
+ self.account_summary[reqId][account][tag] = {
+ "value": value,
+ "currency": currency
+ }
+
+ super().accountSummary(reqId, account, tag, value, currency)
+
+ def accountSummaryEnd(self, reqId: int):
+ """Called when all account summary data has been received."""
+ self._set_event(reqId, "account_summary", self.account_summary.get(reqId, {}))
+ super().accountSummaryEnd(reqId)
+
+ def tickPrice(self, reqId: TickerId, tickType: int, price: float, attrib):
+ """Called when price tick data is returned."""
+ if reqId not in self.market_data:
+ self.market_data[reqId] = {}
+
+ self.market_data[reqId][TickTypeEnum.toStr(tickType)] = price
+
+ # Don't set the event here, wait for snapshot end or a timeout
+ super().tickPrice(reqId, tickType, price, attrib)
+
+ def tickSize(self, reqId: TickerId, tickType: int, size: Decimal):
+ """Called when size tick data is returned."""
+ if reqId not in self.market_data:
+ self.market_data[reqId] = {}
+
+ self.market_data[reqId][TickTypeEnum.toStr(tickType)] = size
+
+ # Don't set the event here, wait for snapshot end or a timeout
+ super().tickSize(reqId, tickType, size)
+
+ def tickString(self, reqId, tickType, value):
+ """Called when string tick data is returned."""
+ if reqId not in self.market_data:
+ self.market_data[reqId] = {}
+ self.market_data[reqId][TickTypeEnum.toStr(tickType)] = value
+
+ def tickGeneric(self, reqId, tickType, value):
+ """Called when generic tick data is returned."""
+ if reqId not in self.market_data:
+ self.market_data[reqId] = {}
+ self.market_data[reqId][TickTypeEnum.toStr(tickType)] = value
+
+ def tickNews(self, reqId, timeStamp, providerCode, articleId, headline, extraData):
+ if reqId not in self.market_data:
+ self.market_data[reqId] = {}
+ if "News" not in self.market_data[reqId].keys():
+ self.market_data[reqId]["News"] = []
+ self.market_data[reqId]["News"].append({"timeStamp": timeStamp, "providerCode":providerCode, "articleId":articleId, "headline": headline, "extraData": extraData})
+
+ def tickSnapshotEnd(self, reqId: int):
+ """Called when all market data for a snapshot has been received."""
+ self._set_event(reqId, "market_data", self.market_data.get(reqId, {}))
+ super().tickSnapshotEnd(reqId)
+
+ def historicalData(self, reqId: int, bar: BarData):
+ """Called when historical data is returned."""
+ if reqId not in self.historical_data:
+ self.historical_data[reqId] = []
+
+ self.historical_data[reqId].append(bar)
+ super().historicalData(reqId, bar)
+
+ def historicalDataEnd(self, reqId: int, start: str, end: str):
+ """Called when all historical data has been received."""
+ self._set_event(reqId, "historical_data", self.historical_data.get(reqId, []))
+ super().historicalDataEnd(reqId, start, end)
+
+ # Synchronous methods
+ def get_next_valid_id(self, timeout=None):
+ """
+ Get the next valid order ID from TWS.
+
+ Args:
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ The next valid order ID
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ self.reqIds(-1)
+ return self._wait_for_response(0, "next_valid_id", timeout)
+
+ def get_current_time(self, timeout=1):
+ """
+ Get the current system time on the server side.
+
+ Args:
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ The current time as an integer (epoch time)
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ self.reqCurrentTime()
+ return self._wait_for_response(0, "current_time", timeout)
+
+ def get_contract_details(self, contract, timeout=5):
+ """
+ Get contract details for a specific contract.
+
+ Args:
+ contract: Contract object
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ A list of ContractDetails objects
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ req_id = self.get_next_valid_id()
+ self.reqContractDetails(req_id, contract)
+ return self._wait_for_response(req_id, "contract_details", timeout)
+
+ def place_order_sync(self, contract, order, timeout=None):
+ """
+ Place an order and wait for the initial order status.
+
+ Args:
+ contract: Contract object
+ order: Order object
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ The order status
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ if timeout is None:
+ timeout = 5 if order.orderType in ["LMT", "MKT"] else 2
+
+ order_id = self.get_next_valid_id()
+ order.orderId = order_id
+
+ # Clear any previous order status for this order ID
+ if order_id in self.order_status:
+ del self.order_status[order_id]
+
+ self.placeOrder(order_id, contract, order)
+ return self._wait_for_response(order_id, "order_status", timeout)
+
+ def cancel_order_sync(self, order_id, orderCancel=None, timeout=3):
+ """
+ Cancel an order and wait for the cancellation status.
+
+ Args:
+ order_id: The order ID to cancel
+ orderCancel: Optional OrderCancel object for additional cancel parameters
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ The order status after cancellation
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ if orderCancel is None:
+ orderCancel = OrderCancel()
+
+ self.cancelOrder(order_id, orderCancel)
+ return self._wait_for_response(order_id, "order_status", timeout)
+
+ def get_open_orders(self, timeout=3):
+ """
+ Get all open orders.
+
+ Args:
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ A dictionary of open orders
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ # Clear existing open orders
+ self.open_orders = {}
+
+ self.reqOpenOrders()
+ return self._wait_for_response(0, "open_orders", timeout)
+
+ def get_executions(self, exec_filter=None, timeout=10):
+ """
+ Get executions matching the filter.
+
+ Args:
+ exec_filter: Optional ExecutionFilter object
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ A list of executions
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ if exec_filter is None:
+ exec_filter = ExecutionFilter()
+
+ req_id = self.get_next_valid_id()
+
+ # Clear existing executions for this request ID
+ if req_id in self.executions:
+ del self.executions[req_id]
+
+ self.reqExecutions(req_id, exec_filter)
+ return self._wait_for_response(req_id, "executions", timeout)
+
+ def get_portfolio(self, account_code="", timeout=None):
+ """
+ Get portfolio information.
+
+ Args:
+ account_code: Account code (empty for all accounts)
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ A list of portfolio items
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ # Clear existing portfolio
+ self.portfolio = []
+
+ self.reqAccountUpdates(True, account_code)
+ portfolio = self._wait_for_response(0, "portfolio", timeout)
+
+ # Stop the updates
+ self.reqAccountUpdates(False, account_code)
+
+ return portfolio
+
+ def get_positions(self, timeout=10):
+ """
+ Get current positions.
+
+ Args:
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ A dictionary of positions by account
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ # Clear existing positions
+ self.positions = {}
+
+ self.reqPositions()
+ positions = self._wait_for_response(0, "positions", timeout)
+
+ # Cancel position updates
+ self.cancelPositions()
+
+ return positions
+
+ def get_account_summary(self, tags, group="All", timeout=5):
+ """
+ Get account summary information.
+
+ Args:
+ tags: Comma-separated string of tags to request
+ group: Account group (default "All")
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ Account summary information
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ req_id = self.get_next_valid_id()
+
+ # Clear existing account summary for this request
+ if req_id in self.account_summary:
+ del self.account_summary[req_id]
+
+ self.reqAccountSummary(req_id, group, tags)
+ summary = self._wait_for_response(req_id, "account_summary", timeout)
+
+ # Cancel the subscription
+ self.cancelAccountSummary(req_id)
+
+ return summary
+
+ def get_market_data_snapshot(self, contract, generic_tick_list="", snapshot=True, timeout=None):
+ """
+ Get a snapshot of market data.
+
+ Args:
+ contract: Contract object
+ generic_tick_list: String of generic tick types
+ snapshot: Whether to request a snapshot
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ Market data
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ if timeout is None:
+ timeout = 11 if snapshot == True else 5
+ req_id = self.get_next_valid_id()
+
+ # Clear existing market data for this request
+ if req_id in self.market_data:
+ del self.market_data[req_id]
+
+ self.reqMktData(req_id, contract, generic_tick_list, snapshot, False, [])
+
+ # For snapshots, we'll get a tickSnapshotEnd event
+ if snapshot:
+ data = self._wait_for_response(req_id, "market_data", timeout)
+ else:
+ # For streaming data, we need to wait a bit and then return what we have
+ time.sleep(1 if timeout is None or timeout > 1 else timeout / 2)
+ data = self.market_data.get(req_id, {})
+
+ # Cancel if not a snapshot (snapshots auto-cancel)
+ if not snapshot:
+ self.cancelMktData(req_id)
+
+ return data
+
+ def get_historical_data(self, contract, end_date_time, duration_str, bar_size_setting,
+ what_to_show, use_rth=True, format_date=1, timeout=30):
+ """
+ Get historical data for a contract.
+
+ Args:
+ contract: Contract object
+ end_date_time: End date and time (format: yyyyMMdd HH:mm:ss)
+ duration_str: Duration string (e.g., "1 D", "1 W")
+ bar_size_setting: Bar size (e.g., "1 min", "1 day")
+ what_to_show: Type of data to show
+ use_rth: Whether to use regular trading hours only
+ format_date: Date format (1 or 2)
+ timeout: Timeout in seconds (uses default if None)
+
+ Returns:
+ Historical bar data
+
+ Raises:
+ ResponseTimeout: If no response is received within the timeout period
+ """
+ req_id = self.get_next_valid_id()
+
+ # Clear existing historical data for this request
+ if req_id in self.historical_data:
+ del self.historical_data[req_id]
+
+ self.reqHistoricalData(req_id, contract, end_date_time, duration_str, bar_size_setting,
+ what_to_show, use_rth, format_date, False, [])
+
+ return self._wait_for_response(req_id, "historical_data", timeout)
+
+ def disconnect_and_stop(self):
+ """Disconnect from TWS and stop the message processing thread."""
+ self.disconnect()
+
+ # Wait for the thread to finish if it's running
+ if hasattr(self, 'api_thread') and self.api_thread.is_alive():
+ self.api_thread.join(timeout=1)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/tag_value.py b/packages/ibkr/ref/source/pythonclient/ibapi/tag_value.py
new file mode 100644
index 00000000..1e74daa8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/tag_value.py
@@ -0,0 +1,22 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+"""
+Simple class mapping a tag to a value. Both of them are strings.
+They are used in a list to convey extra info with the requests.
+"""
+
+from ibapi.object_implem import Object
+
+
+class TagValue(Object):
+ def __init__(self, tag: str = None, value: str = None):
+ self.tag = str(tag)
+ self.value = str(value)
+
+ def __str__(self):
+ # this is not only used for Python dump but when encoding to send
+ # so don't change it lightly !
+ return f"{self.tag}={self.value};"
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/ticktype.py b/packages/ibkr/ref/source/pythonclient/ibapi/ticktype.py
new file mode 100644
index 00000000..87294272
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/ticktype.py
@@ -0,0 +1,117 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+from ibapi.enum_implem import Enum
+
+# TickType
+TickType = int
+TickTypeEnum = Enum(
+ "BID_SIZE",
+ "BID",
+ "ASK",
+ "ASK_SIZE",
+ "LAST",
+ "LAST_SIZE",
+ "HIGH",
+ "LOW",
+ "VOLUME",
+ "CLOSE",
+ "BID_OPTION_COMPUTATION",
+ "ASK_OPTION_COMPUTATION",
+ "LAST_OPTION_COMPUTATION",
+ "MODEL_OPTION",
+ "OPEN",
+ "LOW_13_WEEK",
+ "HIGH_13_WEEK",
+ "LOW_26_WEEK",
+ "HIGH_26_WEEK",
+ "LOW_52_WEEK",
+ "HIGH_52_WEEK",
+ "AVG_VOLUME",
+ "OPEN_INTEREST",
+ "OPTION_HISTORICAL_VOL",
+ "OPTION_IMPLIED_VOL",
+ "OPTION_BID_EXCH",
+ "OPTION_ASK_EXCH",
+ "OPTION_CALL_OPEN_INTEREST",
+ "OPTION_PUT_OPEN_INTEREST",
+ "OPTION_CALL_VOLUME",
+ "OPTION_PUT_VOLUME",
+ "INDEX_FUTURE_PREMIUM",
+ "BID_EXCH",
+ "ASK_EXCH",
+ "AUCTION_VOLUME",
+ "AUCTION_PRICE",
+ "AUCTION_IMBALANCE",
+ "MARK_PRICE",
+ "BID_EFP_COMPUTATION",
+ "ASK_EFP_COMPUTATION",
+ "LAST_EFP_COMPUTATION",
+ "OPEN_EFP_COMPUTATION",
+ "HIGH_EFP_COMPUTATION",
+ "LOW_EFP_COMPUTATION",
+ "CLOSE_EFP_COMPUTATION",
+ "LAST_TIMESTAMP",
+ "SHORTABLE",
+ "FUNDAMENTAL_RATIOS",
+ "RT_VOLUME",
+ "HALTED",
+ "BID_YIELD",
+ "ASK_YIELD",
+ "LAST_YIELD",
+ "CUST_OPTION_COMPUTATION",
+ "TRADE_COUNT",
+ "TRADE_RATE",
+ "VOLUME_RATE",
+ "LAST_RTH_TRADE",
+ "RT_HISTORICAL_VOL",
+ "IB_DIVIDENDS",
+ "BOND_FACTOR_MULTIPLIER",
+ "REGULATORY_IMBALANCE",
+ "NEWS_TICK",
+ "SHORT_TERM_VOLUME_3_MIN",
+ "SHORT_TERM_VOLUME_5_MIN",
+ "SHORT_TERM_VOLUME_10_MIN",
+ "DELAYED_BID",
+ "DELAYED_ASK",
+ "DELAYED_LAST",
+ "DELAYED_BID_SIZE",
+ "DELAYED_ASK_SIZE",
+ "DELAYED_LAST_SIZE",
+ "DELAYED_HIGH",
+ "DELAYED_LOW",
+ "DELAYED_VOLUME",
+ "DELAYED_CLOSE",
+ "DELAYED_OPEN",
+ "RT_TRD_VOLUME",
+ "CREDITMAN_MARK_PRICE",
+ "CREDITMAN_SLOW_MARK_PRICE",
+ "DELAYED_BID_OPTION",
+ "DELAYED_ASK_OPTION",
+ "DELAYED_LAST_OPTION",
+ "DELAYED_MODEL_OPTION",
+ "LAST_EXCH",
+ "LAST_REG_TIME",
+ "FUTURES_OPEN_INTEREST",
+ "AVG_OPT_VOLUME",
+ "DELAYED_LAST_TIMESTAMP",
+ "SHORTABLE_SHARES",
+ "DELAYED_HALTED",
+ "REUTERS_2_MUTUAL_FUNDS",
+ "ETF_NAV_CLOSE",
+ "ETF_NAV_PRIOR_CLOSE",
+ "ETF_NAV_BID",
+ "ETF_NAV_ASK",
+ "ETF_NAV_LAST",
+ "ETF_FROZEN_NAV_LAST",
+ "ETF_NAV_HIGH",
+ "ETF_NAV_LOW",
+ "SOCIAL_MARKET_ANALYTICS",
+ "ESTIMATED_IPO_MIDPOINT",
+ "FINAL_IPO_LAST",
+ "DELAYED_YIELD_BID",
+ "DELAYED_YIELD_ASK",
+ "NOT_SET",
+)
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/utils.py b/packages/ibkr/ref/source/pythonclient/ibapi/utils.py
new file mode 100644
index 00000000..a4dc21db
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/utils.py
@@ -0,0 +1,233 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import sys
+import logging
+import inspect
+import time
+import datetime
+
+from decimal import Decimal
+
+from ibapi.const import (
+ UNSET_INTEGER,
+ UNSET_DOUBLE,
+ UNSET_LONG,
+ UNSET_DECIMAL,
+ DOUBLE_INFINITY,
+ INFINITY_STR,
+)
+
+"""
+Collection of misc tools
+"""
+
+logger = logging.getLogger(__name__)
+
+
+# I use this just to visually emphasize it's a wrapper overridden method
+def iswrapper(fn):
+ return fn
+
+
+class BadMessage(Exception):
+ def __init__(self, text):
+ self.text = text
+
+
+class ClientException(Exception):
+ def __init__(self, code, msg, text):
+ self.code = code
+ self.msg = msg
+ self.text = text
+
+
+class LogFunction(object):
+ def __init__(self, text, logLevel):
+ self.text = text
+ self.logLevel = logLevel
+
+ def __call__(self, fn):
+ def newFn(origSelf, *args, **kwargs):
+ if logger.isEnabledFor(self.logLevel):
+ argNames = [
+ argName
+ for argName in inspect.getfullargspec(fn)[0]
+ if argName != "self"
+ ]
+ logger.log(
+ self.logLevel,
+ "{} {} {} kw:{}",
+ self.text,
+ fn.__name__,
+ [arg for arg in zip(argNames, args) if arg[1] is not origSelf],
+ kwargs,
+ )
+ fn(origSelf, *args)
+
+ return newFn
+
+
+def current_fn_name(parent_idx=0):
+ # depth is 1 bc this is already a fn, so we need the caller
+ return sys._getframe(1 + parent_idx).f_code.co_name
+
+
+def setattr_log(self, var_name, var_value):
+ # import code; code.interact(local=locals())
+ logger.debug("%s %s %s=|%s|", self.__class__, id(self), var_name, var_value)
+ super(self.__class__, self).__setattr__(var_name, var_value)
+
+
+SHOW_UNSET = True
+
+
+def decode(the_type, fields, show_unset=False, use_unicode=False):
+ try:
+ s = next(fields)
+ except StopIteration:
+ raise BadMessage("no more fields")
+
+ logger.debug("decode %s %s", the_type, s)
+
+ if the_type is Decimal:
+ if (
+ s is None
+ or len(s) == 0
+ or s.decode() == "2147483647"
+ or s.decode() == "9223372036854775807"
+ or s.decode() == "1.7976931348623157E308"
+ or s.decode() == "-9223372036854775808"
+ ):
+ return UNSET_DECIMAL
+ return the_type(s.decode())
+
+ if the_type is str:
+ if type(s) is str:
+ return s
+ if type(s) is bytes:
+ return s.decode(
+ "unicode-escape" if use_unicode else "UTF-8", errors="backslashreplace"
+ )
+ else:
+ raise TypeError(
+ "unsupported incoming type " + type(s) + " for desired type 'str"
+ )
+
+ orig_type = the_type
+ if the_type is bool:
+ the_type = int
+
+ if the_type is float:
+ if s.decode() == INFINITY_STR:
+ return DOUBLE_INFINITY
+
+ if show_unset:
+ if s is None or len(s) == 0:
+ if the_type is float:
+ n = UNSET_DOUBLE
+ elif the_type is int:
+ n = UNSET_INTEGER
+ else:
+ raise TypeError("unsupported desired type for empty value" + the_type)
+ else:
+ n = the_type(s)
+ else:
+ n = the_type(s or 0)
+
+ if orig_type is bool:
+ n = n != 0
+
+ return n
+
+
+def ExerciseStaticMethods(klass):
+ import types
+
+ # import code; code.interact(local=dict(globals(), **locals()))
+ for _, var in inspect.getmembers(klass):
+ # print(name, var, type(var))
+ if type(var) == types.FunctionType:
+ print(f"Exercising: {var}:")
+ print(var())
+ print()
+
+def isValidFloatValue(val: float) -> bool:
+ return val != UNSET_DOUBLE
+
+def isValidIntValue(val: int) -> bool:
+ return val != UNSET_INTEGER
+
+def isValidLongValue(val: int) -> bool:
+ return val != UNSET_LONG
+
+def isValidDecimalValue(val: Decimal) -> bool:
+ return val != UNSET_DECIMAL
+
+def floatMaxString(val: float):
+ if val is None:
+ return ""
+ return (
+ f"{val:.8f}".rstrip("0").rstrip(".").rstrip(",") if val != UNSET_DOUBLE else ""
+ )
+
+
+def longMaxString(val):
+ return str(val) if val != UNSET_LONG else ""
+
+
+def intMaxString(val):
+ return str(val) if val != UNSET_INTEGER else ""
+
+
+def isAsciiPrintable(val):
+ return all(ord(c) >= 32 and ord(c) < 127 or ord(c) == 9 or ord(c) == 10 or ord(c) == 13 for c in val)
+
+
+def decimalMaxString(val: Decimal):
+ val = Decimal(str(val)) if type(val) is float else Decimal(val)
+ return f"{val:f}" if val != UNSET_DECIMAL else ""
+
+
+def isPegBenchOrder(orderType: str):
+ return orderType in ("PEG BENCH", "PEGBENCH")
+
+
+def isPegMidOrder(orderType: str):
+ return orderType in ("PEG MID", "PEGMID")
+
+
+def isPegBestOrder(orderType: str):
+ return orderType in ("PEG BEST", "PEGBEST")
+
+
+def log_(func, params, action):
+ if logger.isEnabledFor(logging.INFO):
+ if "self" in params:
+ params = dict(params)
+ del params["self"]
+ logger.info(f"{action} {func} {params}")
+
+def currentTimeMillis() :
+ return round(time.time() * 1000)
+
+def getTimeStrFromMillis(time: int):
+ return datetime.datetime.fromtimestamp(time / 1000.0).strftime("%b %d, %Y %H:%M:%S.%f")[:-3] if time > 0 else ""
+
+def listOfValues(cls):
+ return list(map(lambda c: c, cls))
+
+def getEnumTypeFromString(cls, stringIn):
+ for item in cls:
+ if item.value[0] == stringIn:
+ return item
+ return listOfValues(cls)[0]
+
+def getEnumTypeName(cls, valueIn):
+ for item in cls:
+ if item == valueIn:
+ return item.value[1]
+ return listOfValues(cls)[0].value[1]
+
diff --git a/packages/ibkr/ref/source/pythonclient/ibapi/wrapper.py b/packages/ibkr/ref/source/pythonclient/ibapi/wrapper.py
new file mode 100644
index 00000000..d882a339
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/ibapi/wrapper.py
@@ -0,0 +1,1187 @@
+"""
+Copyright (C) 2025 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+
+This is the interface that will need to be overloaded by the customer so
+that their code can receive info from the TWS/IBGW.
+
+NOTE: the methods use type annotations to describe the types of the arguments.
+This is used by the Decoder to dynamically and automatically decode the
+received message into the given EWrapper method. This method can only be
+used for the most simple messages, but it's still huge helper.
+Also this method currently automatically decode a 'version' field in the
+message. However having a 'version' field is a legacy thing, newer
+message use the 'unified version': the agreed up min version of both
+server and client.
+
+"""
+import logging
+from decimal import Decimal
+
+from ibapi.common import (
+ TickerId,
+ TickAttrib,
+ OrderId,
+ FaDataType,
+ BarData,
+ SetOfString,
+ SetOfFloat,
+ ListOfFamilyCode,
+ ListOfContractDescription,
+ ListOfDepthExchanges,
+ SmartComponentMap,
+ ListOfNewsProviders,
+ HistogramData,
+ ListOfPriceIncrements,
+ ListOfHistoricalTick,
+ ListOfHistoricalTickBidAsk,
+ ListOfHistoricalTickLast,
+ TickAttribLast,
+ TickAttribBidAsk,
+ ListOfHistoricalSessions,
+)
+
+from ibapi.contract import Contract, ContractDetails, DeltaNeutralContract
+from ibapi.order import Order
+from ibapi.order_state import OrderState
+from ibapi.execution import Execution
+
+from ibapi.commission_and_fees_report import CommissionAndFeesReport
+from ibapi.ticktype import TickType
+from ibapi.utils import current_fn_name, log_
+
+from ibapi.protobuf.OrderStatus_pb2 import OrderStatus as OrderStatusProto
+from ibapi.protobuf.OpenOrder_pb2 import OpenOrder as OpenOrderProto
+from ibapi.protobuf.OpenOrdersEnd_pb2 import OpenOrdersEnd as OpenOrdersEndProto
+from ibapi.protobuf.ErrorMessage_pb2 import ErrorMessage as ErrorMessageProto
+from ibapi.protobuf.ExecutionDetails_pb2 import ExecutionDetails as ExecutionDetailsProto
+from ibapi.protobuf.ExecutionDetailsEnd_pb2 import ExecutionDetailsEnd as ExecutionDetailsEndProto
+from ibapi.protobuf.CompletedOrder_pb2 import CompletedOrder as CompletedOrderProto
+from ibapi.protobuf.CompletedOrdersEnd_pb2 import CompletedOrdersEnd as CompletedOrdersEndProto
+from ibapi.protobuf.OrderBound_pb2 import OrderBound as OrderBoundProto
+from ibapi.protobuf.ContractData_pb2 import ContractData as ContractDataProto
+from ibapi.protobuf.ContractDataEnd_pb2 import ContractDataEnd as ContractDataEndProto
+from ibapi.protobuf.TickPrice_pb2 import TickPrice as TickPriceProto
+from ibapi.protobuf.TickSize_pb2 import TickSize as TickSizeProto
+from ibapi.protobuf.TickOptionComputation_pb2 import TickOptionComputation as TickOptionComputationProto
+from ibapi.protobuf.TickGeneric_pb2 import TickGeneric as TickGenericProto
+from ibapi.protobuf.TickString_pb2 import TickString as TickStringProto
+from ibapi.protobuf.TickSnapshotEnd_pb2 import TickSnapshotEnd as TickSnapshotEndProto
+from ibapi.protobuf.MarketDepth_pb2 import MarketDepth as MarketDepthProto
+from ibapi.protobuf.MarketDepthL2_pb2 import MarketDepthL2 as MarketDepthL2Proto
+from ibapi.protobuf.MarketDataType_pb2 import MarketDataType as MarketDataTypeProto
+from ibapi.protobuf.TickReqParams_pb2 import TickReqParams as TickReqParamsProto
+from ibapi.protobuf.AccountValue_pb2 import AccountValue as AccountValueProto
+from ibapi.protobuf.PortfolioValue_pb2 import PortfolioValue as PortfolioValueProto
+from ibapi.protobuf.AccountUpdateTime_pb2 import AccountUpdateTime as AccountUpdateTimeProto
+from ibapi.protobuf.AccountDataEnd_pb2 import AccountDataEnd as AccountDataEndProto
+from ibapi.protobuf.ManagedAccounts_pb2 import ManagedAccounts as ManagedAccountsProto
+from ibapi.protobuf.Position_pb2 import Position as PositionProto
+from ibapi.protobuf.PositionEnd_pb2 import PositionEnd as PositionEndProto
+from ibapi.protobuf.AccountSummary_pb2 import AccountSummary as AccountSummaryProto
+from ibapi.protobuf.AccountSummaryEnd_pb2 import AccountSummaryEnd as AccountSummaryEndProto
+from ibapi.protobuf.PositionMulti_pb2 import PositionMulti as PositionMultiProto
+from ibapi.protobuf.PositionMultiEnd_pb2 import PositionMultiEnd as PositionMultiEndProto
+from ibapi.protobuf.AccountUpdateMulti_pb2 import AccountUpdateMulti as AccountUpdateMultiProto
+from ibapi.protobuf.AccountUpdateMultiEnd_pb2 import AccountUpdateMultiEnd as AccountUpdateMultiEndProto
+from ibapi.protobuf.HistoricalData_pb2 import HistoricalData as HistoricalDataProto
+from ibapi.protobuf.HistoricalDataUpdate_pb2 import HistoricalDataUpdate as HistoricalDataUpdateProto
+from ibapi.protobuf.HistoricalDataEnd_pb2 import HistoricalDataEnd as HistoricalDataEndProto
+from ibapi.protobuf.RealTimeBarTick_pb2 import RealTimeBarTick as RealTimeBarTickProto
+from ibapi.protobuf.HeadTimestamp_pb2 import HeadTimestamp as HeadTimestampProto
+from ibapi.protobuf.HistogramData_pb2 import HistogramData as HistogramDataProto
+from ibapi.protobuf.HistoricalTicks_pb2 import HistoricalTicks as HistoricalTicksProto
+from ibapi.protobuf.HistoricalTicksBidAsk_pb2 import HistoricalTicksBidAsk as HistoricalTicksBidAskProto
+from ibapi.protobuf.HistoricalTicksLast_pb2 import HistoricalTicksLast as HistoricalTicksLastProto
+from ibapi.protobuf.TickByTickData_pb2 import TickByTickData as TickByTickDataProto
+from ibapi.protobuf.NewsBulletin_pb2 import NewsBulletin as NewsBulletinProto
+from ibapi.protobuf.NewsArticle_pb2 import NewsArticle as NewsArticleProto
+from ibapi.protobuf.NewsProviders_pb2 import NewsProviders as NewsProvidersProto
+from ibapi.protobuf.HistoricalNews_pb2 import HistoricalNews as HistoricalNewsProto
+from ibapi.protobuf.HistoricalNewsEnd_pb2 import HistoricalNewsEnd as HistoricalNewsEndProto
+from ibapi.protobuf.WshMetaData_pb2 import WshMetaData as WshMetaDataProto
+from ibapi.protobuf.WshEventData_pb2 import WshEventData as WshEventDataProto
+from ibapi.protobuf.TickNews_pb2 import TickNews as TickNewsProto
+from ibapi.protobuf.ScannerParameters_pb2 import ScannerParameters as ScannerParametersProto
+from ibapi.protobuf.ScannerData_pb2 import ScannerData as ScannerDataProto
+from ibapi.protobuf.FundamentalsData_pb2 import FundamentalsData as FundamentalsDataProto
+from ibapi.protobuf.PnL_pb2 import PnL as PnLProto
+from ibapi.protobuf.PnLSingle_pb2 import PnLSingle as PnLSingleProto
+from ibapi.protobuf.ReceiveFA_pb2 import ReceiveFA as ReceiveFAProto
+from ibapi.protobuf.ReplaceFAEnd_pb2 import ReplaceFAEnd as ReplaceFAEndProto
+from ibapi.protobuf.CommissionAndFeesReport_pb2 import CommissionAndFeesReport as CommissionAndFeesReportProto
+from ibapi.protobuf.HistoricalSchedule_pb2 import HistoricalSchedule as HistoricalScheduleProto
+from ibapi.protobuf.RerouteMarketDataRequest_pb2 import RerouteMarketDataRequest as RerouteMarketDataRequestProto
+from ibapi.protobuf.RerouteMarketDepthRequest_pb2 import RerouteMarketDepthRequest as RerouteMarketDepthRequestProto
+from ibapi.protobuf.SecDefOptParameter_pb2 import SecDefOptParameter as SecDefOptParameterProto
+from ibapi.protobuf.SecDefOptParameterEnd_pb2 import SecDefOptParameterEnd as SecDefOptParameterEndProto
+from ibapi.protobuf.SoftDollarTiers_pb2 import SoftDollarTiers as SoftDollarTiersProto
+from ibapi.protobuf.FamilyCodes_pb2 import FamilyCodes as FamilyCodesProto
+from ibapi.protobuf.SymbolSamples_pb2 import SymbolSamples as SymbolSamplesProto
+from ibapi.protobuf.SmartComponents_pb2 import SmartComponents as SmartComponentsProto
+from ibapi.protobuf.MarketRule_pb2 import MarketRule as MarketRuleProto
+from ibapi.protobuf.UserInfo_pb2 import UserInfo as UserInfoProto
+from ibapi.protobuf.NextValidId_pb2 import NextValidId as NextValidIdProto
+from ibapi.protobuf.CurrentTime_pb2 import CurrentTime as CurrentTimeProto
+from ibapi.protobuf.CurrentTimeInMillis_pb2 import CurrentTimeInMillis as CurrentTimeInMillisProto
+from ibapi.protobuf.VerifyMessageApi_pb2 import VerifyMessageApi as VerifyMessageApiProto
+from ibapi.protobuf.VerifyCompleted_pb2 import VerifyCompleted as VerifyCompletedProto
+from ibapi.protobuf.DisplayGroupList_pb2 import DisplayGroupList as DisplayGroupListProto
+from ibapi.protobuf.DisplayGroupUpdated_pb2 import DisplayGroupUpdated as DisplayGroupUpdatedProto
+from ibapi.protobuf.MarketDepthExchanges_pb2 import MarketDepthExchanges as MarketDepthExchangesProto
+from ibapi.protobuf.ConfigResponse_pb2 import ConfigResponse as ConfigResponseProto
+from ibapi.protobuf.UpdateConfigResponse_pb2 import UpdateConfigResponse as UpdateConfigResponseProto
+
+logger = logging.getLogger(__name__)
+
+
+def logAnswer(fnName, fnParams):
+ log_(fnName, fnParams, "ANSWER")
+
+
+class EWrapper:
+ def __init__(self):
+ pass
+
+ def error(
+ self,
+ reqId: TickerId,
+ errorTime: int,
+ errorCode: int,
+ errorString: str,
+ advancedOrderRejectJson="",
+ ):
+ """This event is called when there is an error with the
+ communication or when TWS wants to send a message to the client."""
+
+ logAnswer(current_fn_name(), vars())
+ if advancedOrderRejectJson:
+ logger.error(
+ "ERROR %s %s %s %s %s",
+ reqId,
+ errorTime,
+ errorCode,
+ errorString,
+ advancedOrderRejectJson,
+ )
+ else:
+ logger.error("ERROR %s %s %s %s", reqId, errorTime, errorCode, errorString)
+
+ def winError(self, text: str, lastError: int):
+ logAnswer(current_fn_name(), vars())
+
+ def connectAck(self):
+ """callback signifying completion of successful connection"""
+ logAnswer(current_fn_name(), vars())
+
+ def marketDataType(self, reqId: TickerId, marketDataType: int):
+ """TWS sends a marketDataType(type) callback to the API, where
+ type is set to Frozen or RealTime, to announce that market data has been
+ switched between frozen and real-time. This notification occurs only
+ when market data switches between real-time and frozen. The
+ marketDataType( ) callback accepts a reqId parameter and is sent per
+ every subscription because different contracts can generally trade on a
+ different schedule."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def tickPrice(
+ self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib
+ ):
+ """Market data tick price callback. Handles all price related ticks."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def tickSize(self, reqId: TickerId, tickType: TickType, size: Decimal):
+ """Market data tick size callback. Handles all size-related ticks."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def tickSnapshotEnd(self, reqId: int):
+ """When requesting market data snapshots, this market will indicate the
+ snapshot reception is finished."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def tickGeneric(self, reqId: TickerId, tickType: TickType, value: float):
+ logAnswer(current_fn_name(), vars())
+
+ def tickString(self, reqId: TickerId, tickType: TickType, value: str):
+ logAnswer(current_fn_name(), vars())
+
+ def tickEFP(
+ self,
+ reqId: TickerId,
+ tickType: TickType,
+ basisPoints: float,
+ formattedBasisPoints: str,
+ totalDividends: float,
+ holdDays: int,
+ futureLastTradeDate: str,
+ dividendImpact: float,
+ dividendsToLastTradeDate: float,
+ ):
+ logAnswer(current_fn_name(), vars())
+ """ market data call back for Exchange for Physical
+ tickerId - The request's identifier.
+ tickType - The type of tick being received.
+ basisPoints - Annualized basis points, which is representative of
+ the financing rate that can be directly compared to broker rates.
+ formattedBasisPoints - Annualized basis points as a formatted string
+ that depicts them in percentage form.
+ impliedFuture - The implied Futures price.
+ holdDays - The number of hold days until the lastTradeDate of the EFP.
+ futureLastTradeDate - The expiration date of the single stock future.
+ dividendImpact - The dividend impact upon the annualized basis points
+ interest rate.
+ dividendsToLastTradeDate - The dividends expected until the expiration
+ of the single stock future."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def orderStatus(
+ self,
+ orderId: OrderId,
+ status: str,
+ filled: Decimal,
+ remaining: Decimal,
+ avgFillPrice: float,
+ permId: int,
+ parentId: int,
+ lastFillPrice: float,
+ clientId: int,
+ whyHeld: str,
+ mktCapPrice: float,
+ ):
+ """This event is called whenever the status of an order changes. It is
+ also fired after reconnecting to TWS if the client has any open orders.
+
+ orderId: OrderId - The order ID that was specified previously in the
+ call to placeOrder()
+ status:str - The order status. Possible values include:
+ PendingSubmit - indicates that you have transmitted the order, but have not yet received confirmation that it has been accepted by the order destination. NOTE: This order status is not sent by TWS and should be explicitly set by the API developer when an order is submitted.
+ PendingCancel - indicates that you have sent a request to cancel the order but have not yet received cancel confirmation from the order destination. At this point, your order is not confirmed canceled. You may still receive an execution while your cancellation request is pending. NOTE: This order status is not sent by TWS and should be explicitly set by the API developer when an order is canceled.
+ PreSubmitted - indicates that a simulated order type has been accepted by the IB system and that this order has yet to be elected. The order is held in the IB system until the election criteria are met. At that time the order is transmitted to the order destination as specified.
+ Submitted - indicates that your order has been accepted at the order destination and is working.
+ Cancelled - indicates that the balance of your order has been confirmed canceled by the IB system. This could occur unexpectedly when IB or the destination has rejected your order.
+ Filled - indicates that the order has been completely filled.
+ Inactive - indicates that the order has been accepted by the system (simulated orders) or an exchange (native orders) but that currently the order is inactive due to system, exchange or other issues.
+ filled:int - Specifies the number of shares that have been executed.
+ For more information about partial fills, see Order Status for Partial Fills.
+ remaining:int - Specifies the number of shares still outstanding.
+ avgFillPrice:float - The average price of the shares that have been executed. This parameter is valid only if the filled parameter value is greater than zero. Otherwise, the price parameter will be zero.
+ permId:int - The TWS id used to identify orders. Remains the same over TWS sessions.
+ parentId:int - The order ID of the parent order, used for bracket and auto trailing stop orders.
+ lastFilledPrice:float - The last price of the shares that have been executed. This parameter is valid only if the filled parameter value is greater than zero. Otherwise, the price parameter will be zero.
+ clientId:int - The ID of the client (or TWS) that placed the order. Note that TWS orders have a fixed clientId and orderId of 0 that distinguishes them from API orders.
+ whyHeld:str - This field is used to identify an order held when TWS is trying to locate shares for a short sell. The value used to indicate this is 'locate'.
+
+ """
+
+ logAnswer(current_fn_name(), vars())
+
+ def openOrder(
+ self, orderId: OrderId, contract: Contract, order: Order, orderState: OrderState
+ ):
+ """This function is called to feed in open orders.
+
+ orderID: OrderId - The order ID assigned by TWS. Use to cancel or
+ update TWS order.
+ contract: Contract - The Contract class attributes describe the contract.
+ order: Order - The Order class gives the details of the open order.
+ orderState: OrderState - The orderState class includes attributes Used
+ for both pre and post trade margin and commission and fees data."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def openOrderEnd(self):
+ """This is called at the end of a given request for open orders."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def connectionClosed(self):
+ """This function is called when TWS closes the sockets
+ connection with the ActiveX control, or when TWS is shut down."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def updateAccountValue(self, key: str, val: str, currency: str, accountName: str):
+ """This function is called only when ReqAccountUpdates on
+ EEClientSocket object has been called."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def updatePortfolio(
+ self,
+ contract: Contract,
+ position: Decimal,
+ marketPrice: float,
+ marketValue: float,
+ averageCost: float,
+ unrealizedPNL: float,
+ realizedPNL: float,
+ accountName: str,
+ ):
+ """This function is called only when reqAccountUpdates on
+ EEClientSocket object has been called."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def updateAccountTime(self, timeStamp: str):
+ logAnswer(current_fn_name(), vars())
+
+ def accountDownloadEnd(self, accountName: str):
+ """This is called after a batch updateAccountValue() and
+ updatePortfolio() is sent."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def nextValidId(self, orderId: int):
+ """Receives next valid order id."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def contractDetails(self, reqId: int, contractDetails: ContractDetails):
+ """Receives the full contract's definitions. This method will return all
+ contracts matching the requested via EEClientSocket::reqContractDetails.
+ For example, one can obtain the whole option chain with it."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def bondContractDetails(self, reqId: int, contractDetails: ContractDetails):
+ """This function is called when reqContractDetails function
+ has been called for bonds."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def contractDetailsEnd(self, reqId: int):
+ """This function is called once all contract details for a given
+ request are received. This helps to define the end of an option
+ chain."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def execDetails(self, reqId: int, contract: Contract, execution: Execution):
+ """This event is fired when the reqExecutions() functions is
+ invoked, or when an order is filled."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def execDetailsEnd(self, reqId: int):
+ """This function is called once all executions have been sent to
+ a client in response to reqExecutions()."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def updateMktDepth(
+ self,
+ reqId: TickerId,
+ position: int,
+ operation: int,
+ side: int,
+ price: float,
+ size: Decimal,
+ ):
+ """Returns the order book.
+
+ tickerId - the request's identifier
+ position - the order book's row being updated
+ operation - how to refresh the row:
+ 0 = insert (insert this new order into the row identified by 'position')
+ 1 = update (update the existing order in the row identified by 'position')
+ 2 = delete (delete the existing order at the row identified by 'position').
+ side - 0 for ask, 1 for bid
+ price - the order's price
+ size - the order's size"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def updateMktDepthL2(
+ self,
+ reqId: TickerId,
+ position: int,
+ marketMaker: str,
+ operation: int,
+ side: int,
+ price: float,
+ size: Decimal,
+ isSmartDepth: bool,
+ ):
+ """Returns the order book.
+
+ tickerId - the request's identifier
+ position - the order book's row being updated
+ marketMaker - the exchange holding the order
+ operation - how to refresh the row:
+ 0 = insert (insert this new order into the row identified by 'position')
+ 1 = update (update the existing order in the row identified by 'position')
+ 2 = delete (delete the existing order at the row identified by 'position').
+ side - 0 for ask, 1 for bid
+ price - the order's price
+ size - the order's size
+ isSmartDepth - is SMART Depth request"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def updateNewsBulletin(
+ self, msgId: int, msgType: int, newsMessage: str, originExch: str
+ ):
+ """provides IB's bulletins
+ msgId - the bulletin's identifier
+ msgType - one of: 1 - Regular news bulletin 2 - Exchange no longer
+ available for trading 3 - Exchange is available for trading
+ message - the message
+ origExchange - the exchange where the message comes from."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def managedAccounts(self, accountsList: str):
+ """Receives a comma-separated string with the managed account ids."""
+ logAnswer(current_fn_name(), vars())
+
+ def receiveFA(self, faData: FaDataType, cxml: str):
+ """receives the Financial Advisor's configuration available in the TWS
+
+ faDataType - one of:
+ Groups: offer traders a way to create a group of accounts and apply
+ a single allocation method to all accounts in the group.
+ Account Aliases: let you easily identify the accounts by meaningful
+ names rather than account numbers.
+ faXmlData - the xml-formatted configuration"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def historicalData(self, reqId: int, bar: BarData):
+ """returns the requested historical data bars
+
+ reqId - the request's identifier
+ date - the bar's date and time (either as a yyyymmss hh:mm:ssformatted
+ string or as system time according to the request)
+ open - the bar's open point
+ high - the bar's high point
+ low - the bar's low point
+ close - the bar's closing point
+ volume - the bar's traded volume if available
+ count - the number of trades during the bar's timespan (only available
+ for TRADES).
+ WAP - the bar's Weighted Average Price
+ hasGaps -indicates if the data has gaps or not."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def historicalDataEnd(self, reqId: int, start: str, end: str):
+ """Marks the ending of the historical bars reception."""
+ logAnswer(current_fn_name(), vars())
+
+ def scannerParameters(self, xml: str):
+ """Provides the xml-formatted parameters available to create a market
+ scanner.
+
+ xml - the xml-formatted string with the available parameters."""
+ logAnswer(current_fn_name(), vars())
+
+ def scannerData(
+ self,
+ reqId: int,
+ rank: int,
+ contractDetails: ContractDetails,
+ distance: str,
+ benchmark: str,
+ projection: str,
+ legsStr: str,
+ ):
+ """Provides the data resulting from the market scanner request.
+
+ reqid - the request's identifier.
+ rank - the ranking within the response of this bar.
+ contractDetails - the data's ContractDetails
+ distance - according to query.
+ benchmark - according to query.
+ projection - according to query.
+ legStr - describes the combo legs when the scanner is returning EFP"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def scannerDataEnd(self, reqId: int):
+ """Indicates the scanner data reception has terminated.
+
+ reqId - the request's identifier"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def realtimeBar(
+ self,
+ reqId: TickerId,
+ time: int,
+ open_: float,
+ high: float,
+ low: float,
+ close: float,
+ volume: Decimal,
+ wap: Decimal,
+ count: int,
+ ):
+ """Updates the real time 5 seconds bars
+
+ reqId - the request's identifier
+ bar.time - start of bar in unix (or 'epoch') time
+ bar.endTime - for synthetic bars, the end time (requires TWS v964). Otherwise -1.
+ bar.open_ - the bar's open value
+ bar.high - the bar's high value
+ bar.low - the bar's low value
+ bar.close - the bar's closing value
+ bar.volume - the bar's traded volume if available
+ bar.WAP - the bar's Weighted Average Price
+ bar.count - the number of trades during the bar's timespan (only available
+ for TRADES)."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def currentTime(self, time: int):
+ """Server's current time. This method will receive IB server's system
+ time resulting after the invocation of reqCurrentTime."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def fundamentalData(self, reqId: TickerId, data: str):
+ """This function is called to receive fundamental
+ market data. The appropriate market data subscription must be set
+ up in Account Management before you can receive this data."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def deltaNeutralValidation(
+ self, reqId: int, deltaNeutralContract: DeltaNeutralContract
+ ):
+ """Upon accepting a Delta-Neutral RFQ(request for quote), the
+ server sends a deltaNeutralValidation() message with the DeltaNeutralContract
+ structure. If the delta and price fields are empty in the original
+ request, the confirmation will contain the current values from the
+ server. These values are locked when the RFQ is processed and remain
+ locked until the RFQ is canceled."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def commissionAndFeesReport(self, commissionAndFeesReport: CommissionAndFeesReport):
+ """The commissionAndFeesReport() callback is triggered as follows:
+ - immediately after a trade execution
+ - by calling reqExecutions()."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def position(
+ self, account: str, contract: Contract, position: Decimal, avgCost: float
+ ):
+ """This event returns real-time positions for all accounts in
+ response to the reqPositions() method."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def positionEnd(self):
+ """This is called once all position data for a given request are
+ received and functions as an end marker for the position() data."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def accountSummary(
+ self, reqId: int, account: str, tag: str, value: str, currency: str
+ ):
+ """Returns the data from the TWS Account Window Summary tab in
+ response to reqAccountSummary()."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def accountSummaryEnd(self, reqId: int):
+ """This method is called once all account summary data for a
+ given request are received."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def verifyMessageAPI(self, apiData: str):
+ """Deprecated Function"""
+ logAnswer(current_fn_name(), vars())
+
+ def verifyCompleted(self, isSuccessful: bool, errorText: str):
+ logAnswer(current_fn_name(), vars())
+
+ def verifyAndAuthMessageAPI(self, apiData: str, xyzChallange: str):
+ logAnswer(current_fn_name(), vars())
+
+ def verifyAndAuthCompleted(self, isSuccessful: bool, errorText: str):
+ logAnswer(current_fn_name(), vars())
+
+ def displayGroupList(self, reqId: int, groups: str):
+ """This callback is a one-time response to queryDisplayGroups().
+
+ reqId - The requestId specified in queryDisplayGroups().
+ groups - A list of integers representing visible group ID separated by
+ the | character, and sorted by most used group first. This list will
+ not change during TWS session (in other words, user cannot add a
+ new group; sorting can change though)."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def displayGroupUpdated(self, reqId: int, contractInfo: str):
+ """This is sent by TWS to the API client once after receiving
+ the subscription request subscribeToGroupEvents(), and will be sent
+ again if the selected contract in the subscribed display group has
+ changed.
+
+ requestId - The requestId specified in subscribeToGroupEvents().
+ contractInfo - The encoded value that uniquely represents the contract
+ in IB. Possible values include:
+ none = empty selection
+ contractID@exchange = any non-combination contract.
+ Examples: 8314@SMART for IBM SMART; 8314@ARCA for IBM @ARCA.
+ combo = if any combo is selected."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def positionMulti(
+ self,
+ reqId: int,
+ account: str,
+ modelCode: str,
+ contract: Contract,
+ pos: Decimal,
+ avgCost: float,
+ ):
+ """same as position() except it can be for a certain
+ account/model"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def positionMultiEnd(self, reqId: int):
+ """same as positionEnd() except it can be for a certain
+ account/model"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def accountUpdateMulti(
+ self,
+ reqId: int,
+ account: str,
+ modelCode: str,
+ key: str,
+ value: str,
+ currency: str,
+ ):
+ """same as updateAccountValue() except it can be for a certain
+ account/model"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def accountUpdateMultiEnd(self, reqId: int):
+ """same as accountDownloadEnd() except it can be for a certain
+ account/model"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def tickOptionComputation(
+ self,
+ reqId: TickerId,
+ tickType: TickType,
+ tickAttrib: int,
+ impliedVol: float,
+ delta: float,
+ optPrice: float,
+ pvDividend: float,
+ gamma: float,
+ vega: float,
+ theta: float,
+ undPrice: float,
+ ):
+ """This function is called when the market in an option or its
+ underlier moves. TWS's option model volatilities, prices, and
+ deltas, along with the present value of dividends expected on that
+ options underlier are received."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def securityDefinitionOptionParameter(
+ self,
+ reqId: int,
+ exchange: str,
+ underlyingConId: int,
+ tradingClass: str,
+ multiplier: str,
+ expirations: SetOfString,
+ strikes: SetOfFloat,
+ ):
+ """Returns the option chain for an underlying on an exchange
+ specified in reqSecDefOptParams There will be multiple callbacks to
+ securityDefinitionOptionParameter if multiple exchanges are specified
+ in reqSecDefOptParams
+
+ reqId - ID of the request initiating the callback
+ underlyingConId - The conID of the underlying security
+ tradingClass - the option trading class
+ multiplier - the option multiplier
+ expirations - a list of the expiries for the options of this underlying
+ on this exchange
+ strikes - a list of the possible strikes for options of this underlying
+ on this exchange"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def securityDefinitionOptionParameterEnd(self, reqId: int):
+ """Called when all callbacks to securityDefinitionOptionParameter are
+ complete
+
+ reqId - the ID used in the call to securityDefinitionOptionParameter"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def softDollarTiers(self, reqId: int, tiers: list):
+ """Called when receives Soft Dollar Tier configuration information
+
+ reqId - The request ID used in the call to EEClient::reqSoftDollarTiers
+ tiers - Stores a list of SoftDollarTier that contains all Soft Dollar
+ Tiers information"""
+
+ logAnswer(current_fn_name(), vars())
+
+ def familyCodes(self, familyCodes: ListOfFamilyCode):
+ """returns array of family codes"""
+ logAnswer(current_fn_name(), vars())
+
+ def symbolSamples(
+ self, reqId: int, contractDescriptions: ListOfContractDescription
+ ):
+ """returns array of sample contract descriptions"""
+ logAnswer(current_fn_name(), vars())
+
+ def mktDepthExchanges(self, depthMktDataDescriptions: ListOfDepthExchanges):
+ """returns array of exchanges which return depth to UpdateMktDepthL2"""
+ logAnswer(current_fn_name(), vars())
+
+ def tickNews(
+ self,
+ tickerId: int,
+ timeStamp: int,
+ providerCode: str,
+ articleId: str,
+ headline: str,
+ extraData: str,
+ ):
+ """returns news headlines"""
+ logAnswer(current_fn_name(), vars())
+
+ def smartComponents(self, reqId: int, smartComponentMap: SmartComponentMap):
+ """returns exchange component mapping"""
+ logAnswer(current_fn_name(), vars())
+
+ def tickReqParams(
+ self, tickerId: int, minTick: float, bboExchange: str, snapshotPermissions: int
+ ):
+ """returns exchange map of a particular contract"""
+ logAnswer(current_fn_name(), vars())
+
+ def newsProviders(self, newsProviders: ListOfNewsProviders):
+ """returns available, subscribed API news providers"""
+ logAnswer(current_fn_name(), vars())
+
+ def newsArticle(self, requestId: int, articleType: int, articleText: str):
+ """returns body of news article"""
+ logAnswer(current_fn_name(), vars())
+
+ def historicalNews(
+ self,
+ requestId: int,
+ time: str,
+ providerCode: str,
+ articleId: str,
+ headline: str,
+ ):
+ """returns historical news headlines"""
+ logAnswer(current_fn_name(), vars())
+
+ def historicalNewsEnd(self, requestId: int, hasMore: bool):
+ """signals end of historical news"""
+ logAnswer(current_fn_name(), vars())
+
+ def headTimestamp(self, reqId: int, headTimestamp: str):
+ """returns earliest available data of a type of data for a particular contract"""
+ logAnswer(current_fn_name(), vars())
+
+ def histogramData(self, reqId: int, items: HistogramData):
+ """returns histogram data for a contract"""
+ logAnswer(current_fn_name(), vars())
+
+ def historicalDataUpdate(self, reqId: int, bar: BarData):
+ """returns updates in real time when keepUpToDate is set to True"""
+ logAnswer(current_fn_name(), vars())
+
+ def rerouteMktDataReq(self, reqId: int, conId: int, exchange: str):
+ """returns reroute CFD contract information for market data request"""
+ logAnswer(current_fn_name(), vars())
+
+ def rerouteMktDepthReq(self, reqId: int, conId: int, exchange: str):
+ """returns reroute CFD contract information for market depth request"""
+ logAnswer(current_fn_name(), vars())
+
+ def marketRule(self, marketRuleId: int, priceIncrements: ListOfPriceIncrements):
+ """returns minimum price increment structure for a particular market rule ID"""
+ logAnswer(current_fn_name(), vars())
+
+ def pnl(
+ self, reqId: int, dailyPnL: float, unrealizedPnL: float, realizedPnL: float
+ ):
+ """returns the daily PnL for the account"""
+ logAnswer(current_fn_name(), vars())
+
+ def pnlSingle(
+ self,
+ reqId: int,
+ pos: Decimal,
+ dailyPnL: float,
+ unrealizedPnL: float,
+ realizedPnL: float,
+ value: float,
+ ):
+ """returns the daily PnL for a single position in the account"""
+ logAnswer(current_fn_name(), vars())
+
+ def historicalTicks(self, reqId: int, ticks: ListOfHistoricalTick, done: bool):
+ """returns historical tick data when whatToShow=MIDPOINT"""
+ logAnswer(current_fn_name(), vars())
+
+ def historicalTicksBidAsk(
+ self, reqId: int, ticks: ListOfHistoricalTickBidAsk, done: bool
+ ):
+ """returns historical tick data when whatToShow=BID_ASK"""
+ logAnswer(current_fn_name(), vars())
+
+ def historicalTicksLast(
+ self, reqId: int, ticks: ListOfHistoricalTickLast, done: bool
+ ):
+ """returns historical tick data when whatToShow=TRADES"""
+ logAnswer(current_fn_name(), vars())
+
+ def tickByTickAllLast(
+ self,
+ reqId: int,
+ tickType: int,
+ time: int,
+ price: float,
+ size: Decimal,
+ tickAttribLast: TickAttribLast,
+ exchange: str,
+ specialConditions: str,
+ ):
+ """returns tick-by-tick data for tickType = "Last" or "AllLast" """
+ logAnswer(current_fn_name(), vars())
+
+ def tickByTickBidAsk(
+ self,
+ reqId: int,
+ time: int,
+ bidPrice: float,
+ askPrice: float,
+ bidSize: Decimal,
+ askSize: Decimal,
+ tickAttribBidAsk: TickAttribBidAsk,
+ ):
+ """returns tick-by-tick data for tickType = "BidAsk" """
+ logAnswer(current_fn_name(), vars())
+
+ def tickByTickMidPoint(self, reqId: int, time: int, midPoint: float):
+ """returns tick-by-tick data for tickType = "MidPoint" """
+ logAnswer(current_fn_name(), vars())
+
+ def orderBound(self, permId: int, clientId: int, orderId: int):
+ """returns orderBound notification"""
+ logAnswer(current_fn_name(), vars())
+
+ def completedOrder(self, contract: Contract, order: Order, orderState: OrderState):
+ """This function is called to feed in completed orders.
+
+ contract: Contract - The Contract class attributes describe the contract.
+ order: Order - The Order class gives the details of the completed order.
+ orderState: OrderState - The orderState class includes completed order status details.
+ """
+
+ logAnswer(current_fn_name(), vars())
+
+ def completedOrdersEnd(self):
+ """This is called at the end of a given request for completed orders."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def replaceFAEnd(self, reqId: int, text: str):
+ """This is called at the end of a replace FA."""
+
+ logAnswer(current_fn_name(), vars())
+
+ def wshMetaData(self, reqId: int, dataJson: str):
+ logAnswer(current_fn_name(), vars())
+
+ def wshEventData(self, reqId: int, dataJson: str):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalSchedule(
+ self,
+ reqId: int,
+ startDateTime: str,
+ endDateTime: str,
+ timeZone: str,
+ sessions: ListOfHistoricalSessions,
+ ):
+ """returns historical schedule for historical data request with whatToShow=SCHEDULE"""
+ logAnswer(current_fn_name(), vars())
+
+ def userInfo(self, reqId: int, whiteBrandingId: str):
+ """returns user info"""
+ logAnswer(current_fn_name(), vars())
+
+ def currentTimeInMillis(self, timeInMillis: int):
+ """Server's current time in milliseconds. This method will receive IB server's system
+ time in milliseconds resulting after the invocation of reqCurrentTimeInMillis."""
+ logAnswer(current_fn_name(), vars())
+
+ # Protobuf
+ def orderStatusProtoBuf(self, orderStatusProto: OrderStatusProto):
+ logAnswer(current_fn_name(), vars())
+
+ def openOrderProtoBuf(self, openOrderProto: OpenOrderProto):
+ logAnswer(current_fn_name(), vars())
+
+ def openOrdersEndProtoBuf(self, openOrdersEndProto: OpenOrdersEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def errorProtoBuf(self, errorMessageProto: ErrorMessageProto):
+ logAnswer(current_fn_name(), vars())
+
+ def executionDetailsProtoBuf(self, executionDetailsProto: ExecutionDetailsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def executionDetailsEndProtoBuf(self, executionDetailsProto: ExecutionDetailsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def completedOrderProtoBuf(self, completedOrderProto: CompletedOrderProto):
+ logAnswer(current_fn_name(), vars())
+
+ def completedOrdersEndProtoBuf(self, completedOrdersEndProto: CompletedOrdersEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def orderBoundProtoBuf(self, orderBoundProto: OrderBoundProto):
+ logAnswer(current_fn_name(), vars())
+
+ def contractDataProtoBuf(self, contractDataProto: ContractDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def bondContractDataProtoBuf(self, contractDataProto: ContractDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def contractDataEndProtoBuf(self, contractDataEndProto: ContractDataEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickPriceProtoBuf(self, tickPriceProto: TickPriceProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickSizeProtoBuf(self, tickSizeProto: TickSizeProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickOptionComputationProtoBuf(self, tickOptionComputationProto: TickOptionComputationProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickGenericProtoBuf(self, tickGenericProto: TickGenericProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickStringProtoBuf(self, tickStringProto: TickStringProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickSnapshotEndProtoBuf(self, tickSnapshotEndProto: TickSnapshotEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateMarketDepthProtoBuf(self, marketDepthProto: MarketDepthProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateMarketDepthL2ProtoBuf(self, marketDepthL2Proto: MarketDepthL2Proto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateMarketDataTypeProtoBuf(self, marketDataTypeProto: MarketDataTypeProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickReqParamsProtoBuf(self, tickReqParamsProto: TickReqParamsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateAccountValueProtoBuf(self, accountValueProto: AccountValueProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updatePortfolioProtoBuf(self, portfolioValueProto: PortfolioValueProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateAccountTimeProtoBuf(self, accountUpdateTimeProto: AccountUpdateTimeProto):
+ logAnswer(current_fn_name(), vars())
+
+ def accountDataEndProtoBuf(self, accountDataEndProto: AccountDataEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def managedAccountsProtoBuf(self, managedAccountsProto: ManagedAccountsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def positionProtoBuf(self, positionProto: PositionProto):
+ logAnswer(current_fn_name(), vars())
+
+ def positionEndProtoBuf(self, positionEndProto: PositionEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def accountSummaryProtoBuf(self, accountSummaryProto: AccountSummaryProto):
+ logAnswer(current_fn_name(), vars())
+
+ def accountSummaryEndProtoBuf(self, accountSummaryEndProto: AccountSummaryEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def positionMultiProtoBuf(self, positionMultiProto: PositionMultiProto):
+ logAnswer(current_fn_name(), vars())
+
+ def positionMultiEndProtoBuf(self, positionMultiEndProto: PositionMultiEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def accountUpdateMultiProtoBuf(self, accountUpdateMultiProto: AccountUpdateMultiProto):
+ logAnswer(current_fn_name(), vars())
+
+ def accountUpdateMultiEndProtoBuf(self, accountUpdateMultiEndProto: AccountUpdateMultiEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalDataProtoBuf(self, historicalDataProto: HistoricalDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalDataUpdateProtoBuf(self, historicalDataUpdateProto: HistoricalDataUpdateProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalDataEndProtoBuf(self, historicalDataEndProto: HistoricalDataEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def realTimeBarTickProtoBuf(self, realTimeBarTickProto: RealTimeBarTickProto):
+ logAnswer(current_fn_name(), vars())
+
+ def headTimestampProtoBuf(self, headTimestampProto: HeadTimestampProto):
+ logAnswer(current_fn_name(), vars())
+
+ def histogramDataProtoBuf(self, histogramDataProto: HistogramDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalTicksProtoBuf(self, historicalTicksProto: HistoricalTicksProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalTicksBidAskProtoBuf(self, historicalTicksBidAskProto: HistoricalTicksBidAskProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalTicksLastProtoBuf(self, historicalTicksLastProto: HistoricalTicksLastProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickByTickDataProtoBuf(self, tickByTickDataProto: TickByTickDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateNewsBulletinProtoBuf(self, newsBulletinProto: NewsBulletinProto):
+ logAnswer(current_fn_name(), vars())
+
+ def newsArticleProtoBuf(self, newsArticleProto: NewsArticleProto):
+ logAnswer(current_fn_name(), vars())
+
+ def newsProvidersProtoBuf(self, newsProvidersProto: NewsProvidersProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalNewsProtoBuf(self, historicalNewsProto: HistoricalNewsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalNewsEndProtoBuf(self, historicalNewsEndProto: HistoricalNewsEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def wshMetaDataProtoBuf(self, wshMetaDataProto: WshMetaDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def wshEventDataProtoBuf(self, wshEventDataProto: WshEventDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def tickNewsProtoBuf(self, tickNewsProto: TickNewsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def scannerParametersProtoBuf(self, scannerParametersProto: ScannerParametersProto):
+ logAnswer(current_fn_name(), vars())
+
+ def scannerDataProtoBuf(self, scannerDataProto: ScannerDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def fundamentalsDataProtoBuf(self, fundamentalsDataProto: FundamentalsDataProto):
+ logAnswer(current_fn_name(), vars())
+
+ def pnlProtoBuf(self, pnlProto: PnLProto):
+ logAnswer(current_fn_name(), vars())
+
+ def pnlSingleProtoBuf(self, pnlSingleProto: PnLSingleProto):
+ logAnswer(current_fn_name(), vars())
+
+ def receiveFAProtoBuf(self, receiveFAProto: ReceiveFAProto):
+ logAnswer(current_fn_name(), vars())
+
+ def replaceFAEndProtoBuf(self, replaceFAEndProto: ReplaceFAEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def commissionAndFeesReportProtoBuf(self, commissionAndFeesReportProto: CommissionAndFeesReportProto):
+ logAnswer(current_fn_name(), vars())
+
+ def historicalScheduleProtoBuf(self, historicalScheduleProto: HistoricalScheduleProto):
+ logAnswer(current_fn_name(), vars())
+
+ def rerouteMarketDataRequestProtoBuf(self, rerouteMarketDataRequestProto: RerouteMarketDataRequestProto):
+ logAnswer(current_fn_name(), vars())
+
+ def rerouteMarketDepthRequestProtoBuf(self, rerouteMarketDepthRequestProto: RerouteMarketDepthRequestProto):
+ logAnswer(current_fn_name(), vars())
+
+ def secDefOptParameterProtoBuf(self, secDefOptParameterProto: SecDefOptParameterProto):
+ logAnswer(current_fn_name(), vars())
+
+ def secDefOptParameterEndProtoBuf(self, secDefOptParameterEndProto: SecDefOptParameterEndProto):
+ logAnswer(current_fn_name(), vars())
+
+ def softDollarTiersProtoBuf(self, softDollarTiersProto: SoftDollarTiersProto):
+ logAnswer(current_fn_name(), vars())
+
+ def familyCodesProtoBuf(self, familyCodesProto: FamilyCodesProto):
+ logAnswer(current_fn_name(), vars())
+
+ def symbolSamplesProtoBuf(self, symbolSamplesProto: SymbolSamplesProto):
+ logAnswer(current_fn_name(), vars())
+
+ def smartComponentsProtoBuf(self, smartComponentsProto: SmartComponentsProto):
+ logAnswer(current_fn_name(), vars())
+
+ def marketRuleProtoBuf(self, marketRuleProto: MarketRuleProto):
+ logAnswer(current_fn_name(), vars())
+
+ def userInfoProtoBuf(self, userInfoProto: UserInfoProto):
+ logAnswer(current_fn_name(), vars())
+
+ def nextValidIdProtoBuf(self, nextValidIdProto: NextValidIdProto):
+ logAnswer(current_fn_name(), vars())
+
+ def currentTimeProtoBuf(self, currentTimeProto: CurrentTimeProto):
+ logAnswer(current_fn_name(), vars())
+
+ def currentTimeInMillisProtoBuf(self, currentTimeInMillisProto: CurrentTimeInMillisProto):
+ logAnswer(current_fn_name(), vars())
+
+ def verifyMessageApiProtoBuf(self, verifyMessageApiProto: VerifyMessageApiProto):
+ logAnswer(current_fn_name(), vars())
+
+ def verifyCompletedProtoBuf(self, verifyCompletedProto: VerifyCompletedProto):
+ logAnswer(current_fn_name(), vars())
+
+ def displayGroupListProtoBuf(self, displayGroupListProto: DisplayGroupListProto):
+ logAnswer(current_fn_name(), vars())
+
+ def displayGroupUpdatedProtoBuf(self, displayGroupUpdatedProto: DisplayGroupUpdatedProto):
+ logAnswer(current_fn_name(), vars())
+
+ def marketDepthExchangesProtoBuf(self, marketDepthExchangesProto: MarketDepthExchangesProto):
+ logAnswer(current_fn_name(), vars())
+
+ def configResponseProtoBuf(self, configResponseProto: ConfigResponseProto):
+ logAnswer(current_fn_name(), vars())
+
+ def updateConfigResponseProtoBuf(self, updateConfigResponseProto: UpdateConfigResponseProto):
+ logAnswer(current_fn_name(), vars())
diff --git a/packages/ibkr/ref/source/pythonclient/pylintrc b/packages/ibkr/ref/source/pythonclient/pylintrc
new file mode 100644
index 00000000..33340204
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/pylintrc
@@ -0,0 +1,634 @@
+[MAIN]
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Clear in-memory caches upon conclusion of linting. Useful if running pylint
+# in a server-like mode.
+clear-cache-post-run=no
+
+# Load and enable all available extensions. Use --list-extensions to see a list
+# all available extensions.
+#enable-all-extensions=
+
+# In error mode, messages with a category besides ERROR or FATAL are
+# suppressed, and no reports are done by default. Error mode is compatible with
+# disabling specific errors.
+#errors-only=
+
+# Always return a 0 (non-error) status code, even if lint errors are found.
+# This is primarily useful in continuous integration scripts.
+#exit-zero=
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code.
+extension-pkg-allow-list=
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
+# for backward compatibility.)
+extension-pkg-whitelist=
+
+# Return non-zero exit code if any of these messages/categories are detected,
+# even if score is above --fail-under value. Syntax same as enable. Messages
+# specified are enabled, while categories only check already-enabled messages.
+fail-on=
+
+# Specify a score threshold under which the program will exit with error.
+fail-under=10
+
+# Interpret the stdin as a python script, whose filename needs to be passed as
+# the module_or_package argument.
+#from-stdin=
+
+# Files or directories to be skipped. They should be base names, not paths.
+ignore=CVS
+
+# Add files or directories matching the regular expressions patterns to the
+# ignore-list. The regex matches against paths and can be in Posix or Windows
+# format. Because '\\' represents the directory delimiter on Windows systems,
+# it can't be used as an escape character.
+ignore-paths=
+
+# Files or directories matching the regular expression patterns are skipped.
+# The regex matches against base names, not paths. The default value ignores
+# Emacs file locks
+ignore-patterns=^\.#
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis). It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
+# number of processors available to use, and will cap the count on Windows to
+# avoid hangs.
+jobs=1
+
+# Control the amount of potential inferred values when inferring a single
+# object. This can help the performance when dealing with large functions or
+# complex, nested conditions.
+limit-inference-results=100
+
+# List of plugins (as comma separated values of python module names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Minimum Python version to use for version dependent checks. Will default to
+# the version used to run pylint.
+py-version=3.10
+
+# Discover python modules and packages in the file system subtree.
+recursive=no
+
+# Add paths to the list of the source roots. Supports globbing patterns. The
+# source root is an absolute path or a path relative to the current working
+# directory used to determine a package namespace for modules located under the
+# source root.
+source-roots=
+
+# When enabled, pylint would attempt to guess common misconfiguration and emit
+# user-friendly hints instead of false-positive error messages.
+suggestion-mode=yes
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+# In verbose mode, extra non-checker-related info will be displayed.
+#verbose=
+
+
+[BASIC]
+
+# Naming style matching correct argument names.
+argument-naming-style=camelCase
+
+# Regular expression matching correct argument names. Overrides argument-
+# naming-style. If left empty, argument names will be checked with the set
+# naming style.
+#argument-rgx=
+
+# Naming style matching correct attribute names.
+attr-naming-style=camelCase
+
+# Regular expression matching correct attribute names. Overrides attr-naming-
+# style. If left empty, attribute names will be checked with the set naming
+# style.
+#attr-rgx=
+
+# Bad variable names which should always be refused, separated by a comma.
+bad-names=foo,
+ bar,
+ baz,
+ toto,
+ tutu,
+ tata
+
+# Bad variable names regexes, separated by a comma. If names match any regex,
+# they will always be refused
+bad-names-rgxs=
+
+# Naming style matching correct class attribute names.
+class-attribute-naming-style=any
+
+# Regular expression matching correct class attribute names. Overrides class-
+# attribute-naming-style. If left empty, class attribute names will be checked
+# with the set naming style.
+#class-attribute-rgx=
+
+# Naming style matching correct class constant names.
+class-const-naming-style=UPPER_CASE
+
+# Regular expression matching correct class constant names. Overrides class-
+# const-naming-style. If left empty, class constant names will be checked with
+# the set naming style.
+#class-const-rgx=
+
+# Naming style matching correct class names.
+class-naming-style=PascalCase
+
+# Regular expression matching correct class names. Overrides class-naming-
+# style. If left empty, class names will be checked with the set naming style.
+#class-rgx=
+
+# Naming style matching correct constant names.
+const-naming-style=UPPER_CASE
+
+# Regular expression matching correct constant names. Overrides const-naming-
+# style. If left empty, constant names will be checked with the set naming
+# style.
+#const-rgx=
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+# Naming style matching correct function names.
+function-naming-style=camelCase
+
+# Regular expression matching correct function names. Overrides function-
+# naming-style. If left empty, function names will be checked with the set
+# naming style.
+#function-rgx=
+
+# Good variable names which should always be accepted, separated by a comma.
+good-names=i,
+ j,
+ k,
+ ex,
+ Run,
+ _
+
+# Good variable names regexes, separated by a comma. If names match any regex,
+# they will always be accepted
+good-names-rgxs=
+
+# Include a hint for the correct naming format with invalid-name.
+include-naming-hint=no
+
+# Naming style matching correct inline iteration names.
+inlinevar-naming-style=any
+
+# Regular expression matching correct inline iteration names. Overrides
+# inlinevar-naming-style. If left empty, inline iteration names will be checked
+# with the set naming style.
+#inlinevar-rgx=
+
+# Naming style matching correct method names.
+method-naming-style=camelCase
+
+# Regular expression matching correct method names. Overrides method-naming-
+# style. If left empty, method names will be checked with the set naming style.
+#method-rgx=
+
+# Naming style matching correct module names.
+module-naming-style=snake_case
+
+# Regular expression matching correct module names. Overrides module-naming-
+# style. If left empty, module names will be checked with the set naming style.
+#module-rgx=
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+# These decorators are taken in consideration only for invalid-name.
+property-classes=abc.abstractproperty
+
+# Regular expression matching correct type alias names. If left empty, type
+# alias names will be checked with the set naming style.
+#typealias-rgx=
+
+# Regular expression matching correct type variable names. If left empty, type
+# variable names will be checked with the set naming style.
+#typevar-rgx=
+
+# Naming style matching correct variable names.
+variable-naming-style=camelCase
+
+# Regular expression matching correct variable names. Overrides variable-
+# naming-style. If left empty, variable names will be checked with the set
+# naming style.
+#variable-rgx=
+
+
+[CLASSES]
+
+# Warn about protected attribute access inside special methods
+check-protected-access-in-special-methods=no
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+ __new__,
+ setUp,
+ asyncSetUp,
+ __post_init__
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# List of regular expressions of class ancestor names to ignore when counting
+# public methods (see R0903)
+exclude-too-few-public-methods=
+
+# List of qualified class names to ignore when counting class parents (see
+# R0901)
+ignored-parents=
+
+# Maximum number of arguments for function / method.
+max-args=5
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Maximum number of boolean expressions in an if statement (see R0916).
+max-bool-expr=5
+
+# Maximum number of branch for function / method body.
+max-branches=12
+
+# Maximum number of locals for function / method body.
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body.
+max-returns=6
+
+# Maximum number of statements in function / method body.
+max-statements=50
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when caught.
+overgeneral-exceptions=builtins.BaseException,builtins.Exception
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+expected-line-ending-format=
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )??$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=120
+
+# Maximum number of lines in a module.
+max-module-lines=1000
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
+[IMPORTS]
+
+# List of modules that can be imported at any level, not just the top level
+# one.
+allow-any-import-level=
+
+# Allow explicit reexports by alias from a package __init__.
+allow-reexport-from-package=no
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Deprecated modules which should not be used, separated by a comma.
+deprecated-modules=
+
+# Output a graph (.gv or any supported image format) of external dependencies
+# to the given file (report RP0402 must not be disabled).
+ext-import-graph=
+
+# Output a graph (.gv or any supported image format) of all (i.e. internal and
+# external) dependencies to the given file (report RP0402 must not be
+# disabled).
+import-graph=
+
+# Output a graph (.gv or any supported image format) of internal dependencies
+# to the given file (report RP0402 must not be disabled).
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+# Couples of modules and preferred modules, separated by a comma.
+preferred-modules=
+
+
+[LOGGING]
+
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format.
+logging-modules=logging
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
+# UNDEFINED.
+confidence=HIGH,
+ CONTROL_FLOW,
+ INFERENCE,
+ INFERENCE_FAILURE,
+ UNDEFINED
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then re-enable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=raw-checker-failed,
+ bad-inline-option,
+ locally-disabled,
+ file-ignored,
+ suppressed-message,
+ useless-suppression,
+ deprecated-pragma,
+ use-symbolic-message-instead,
+ use-implicit-booleaness-not-comparison-to-string,
+ use-implicit-booleaness-not-comparison-to-zero
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=
+
+
+[METHOD_ARGS]
+
+# List of qualified names (i.e., library.method) which require a timeout
+# parameter e.g. 'requests.api.get,requests.api.post'
+timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,
+ XXX,
+ TODO
+
+# Regular expression of note tags to take in consideration.
+notes-rgx=
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit,argparse.parse_error
+
+
+[REPORTS]
+
+# Python expression which should return a score less than or equal to 10. You
+# have access to the variables 'fatal', 'error', 'warning', 'refactor',
+# 'convention', and 'info' which contain the number of messages in each
+# category, as well as 'statement' which is the total number of statements
+# analyzed. This score is used by the global evaluation report (RP0004).
+evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details.
+msg-template=
+
+# Set the output format. Available formats are: text, parseable, colorized,
+# json2 (improved json format), json (old json format) and msvs (visual
+# studio). You can also give a reporter class, e.g.
+# mypackage.mymodule.MyReporterClass.
+#output-format=
+
+# Tells whether to display a full report or only the messages.
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[SIMILARITIES]
+
+# Comments are removed from the similarity computation
+ignore-comments=yes
+
+# Docstrings are removed from the similarity computation
+ignore-docstrings=yes
+
+# Imports are removed from the similarity computation
+ignore-imports=yes
+
+# Signatures are removed from the similarity computation
+ignore-signatures=yes
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[SPELLING]
+
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+
+# Spelling dictionary name. No available dictionaries : You need to install
+# both the python package and the system dependency for enchant to work.
+spelling-dict=
+
+# List of comma separated words that should be considered directives if they
+# appear at the beginning of a comment and should not be checked.
+spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to the private dictionary (see the
+# --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[STRING]
+
+# This flag controls whether inconsistent-quotes generates a warning when the
+# character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=no
+
+# This flag controls whether the implicit-str-concat should generate a warning
+# on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=no
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+# Tells whether to warn about missing members when the owner of the attribute
+# is inferred to be None.
+ignore-none=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of symbolic message names to ignore for Mixin members.
+ignored-checks-for-mixins=no-member,
+ not-async-context-manager,
+ not-context-manager,
+ attribute-defined-outside-init
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+# Regex pattern to define which classes are considered mixins.
+mixin-class-rgx=.*[Mm]ixin
+
+# List of decorators that change the signature of a decorated function.
+signature-mutators=
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid defining new builtins when possible.
+additional-builtins=
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of names allowed to shadow builtins
+allowed-redefined-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+ _cb
+
+# A regular expression matching the name of dummy variables (i.e. expected to
+# not be used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored.
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
diff --git a/packages/ibkr/ref/source/pythonclient/setup.py b/packages/ibkr/ref/source/pythonclient/setup.py
new file mode 100644
index 00000000..66599fe0
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/setup.py
@@ -0,0 +1,24 @@
+"""
+Copyright (C) 2024 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+# from distutils.core import setup
+from setuptools import setup
+from ibapi import get_version_string
+
+import sys
+
+if sys.version_info < (3, 1):
+ sys.exit("Only Python 3.1 and greater is supported")
+
+setup(
+ name="ibapi",
+ version=get_version_string(),
+ packages=["ibapi","ibapi/protobuf"],
+ install_requires=["protobuf==5.29.5"],
+ url="https://interactivebrokers.github.io/tws-api",
+ license="IB API Non-Commercial License or the IB API Commercial License",
+ author="IBG LLC",
+ author_email="api@interactivebrokers.com",
+ description="Python IB API",
+)
diff --git a/packages/ibkr/ref/source/pythonclient/tests/manual.py b/packages/ibkr/ref/source/pythonclient/tests/manual.py
new file mode 100644
index 00000000..b21c36e1
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tests/manual.py
@@ -0,0 +1,259 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import argparse
+import datetime
+
+from ibapi.client import EClient
+from ibapi.common import *
+from ibapi.contract import *
+from ibapi.order import *
+from ibapi.order_condition import *
+from ibapi.order_state import *
+from ibapi.scanner import ScannerSubscription
+from ibapi.ticktype import TickType, TickTypeEnum
+from ibapi.utils import *
+from ibapi.wrapper import EWrapper
+
+
+# import pdb; pdb.set_trace()
+# import code; code.interact(local=locals())
+# import code; code.interact(local=dict(globals(), **locals()))
+
+
+class TestApp(EClient, EWrapper):
+ def __init__(self):
+ EClient.__init__(self, self)
+ self.nextValidOrderId = None
+ self.permId2ord = {}
+
+ @iswrapper
+ def nextValidId(self, orderId: int):
+ super().nextValidId(orderId)
+ logging.debug("setting nextValidOrderId: %d", orderId)
+ self.nextValidOrderId = orderId
+
+ def placeOneOrder(self):
+ con = Contract()
+ con.symbol = "AMD"
+ con.secType = "STK"
+ con.currency = "USD"
+ con.exchange = "SMART"
+ order = Order()
+ order.action = "BUY"
+ order.orderType = "LMT"
+ order.tif = "GTC"
+ order.totalQuantity = 3
+ order.lmtPrice = 1.23
+ self.placeOrder(self.nextOrderId(), con, order)
+
+ def cancelOneOrder(self):
+ pass
+
+ def nextOrderId(self):
+ id_ = self.nextValidOrderId
+ self.nextValidOrderId += 1
+ return id_
+
+ @iswrapper
+ def error(self, *args):
+ super().error(*args)
+ print(current_fn_name(), vars())
+
+ @iswrapper
+ def winError(self, *args):
+ super().error(*args)
+ print(current_fn_name(), vars())
+
+ @iswrapper
+ def openOrder(
+ self, orderId: OrderId, contract: Contract, order: Order, orderState: OrderState
+ ):
+ super().openOrder(orderId, contract, order, orderState)
+ print(current_fn_name(), vars())
+
+ order.contract = contract
+ self.permId2ord[order.permId] = order
+
+ @iswrapper
+ def openOrderEnd(self, *args):
+ super().openOrderEnd()
+ logging.debug("Received %d openOrders", len(self.permId2ord))
+
+ @iswrapper
+ def orderStatus(
+ self,
+ orderId: OrderId,
+ status: str,
+ filled: float,
+ remaining: float,
+ avgFillPrice: float,
+ permId: int,
+ parentId: int,
+ lastFillPrice: float,
+ clientId: int,
+ whyHeld: str,
+ ):
+ super().orderStatus(
+ orderId,
+ status,
+ Decimal(filled),
+ Decimal(remaining),
+ avgFillPrice,
+ permId,
+ parentId,
+ lastFillPrice,
+ clientId,
+ whyHeld,
+ 0,
+ )
+
+ @iswrapper
+ def tickPrice(self, tickerId: TickerId, tickType: TickType, price: float, attrib):
+ super().tickPrice(tickerId, tickType, price, attrib)
+ print(
+ current_fn_name(),
+ tickerId,
+ TickTypeEnum.toStr(tickType),
+ price,
+ attrib,
+ file=sys.stderr,
+ )
+
+ @iswrapper
+ def tickSize(self, tickerId: TickerId, tickType: TickType, size: int):
+ super().tickSize(tickerId, tickType, Decimal(size))
+ print(
+ current_fn_name(),
+ tickerId,
+ TickTypeEnum.toStr(tickType),
+ size,
+ file=sys.stderr,
+ )
+
+ @iswrapper
+ def scannerParameters(self, xml: str):
+ open("scanner.xml", "w").write(xml)
+
+
+def main():
+ cmdLineParser = argparse.ArgumentParser("api tests")
+ # cmdLineParser.add_option("-c", action="store_true", dest="use_cache", default = False, help = "use the cache")
+ # cmdLineParser.add_option("-f", action="store", type="string", dest="file", default="", help="the input file")
+ cmdLineParser.add_argument(
+ "-p",
+ "--port",
+ action="store",
+ type=int,
+ dest="port",
+ default=4005,
+ help="The TCP port to use",
+ )
+ args = cmdLineParser.parse_args()
+ print("Using args", args)
+
+ import logging
+
+ logging.debug("Using args %s", args)
+ # print(args)
+
+ logging.debug("now is %s", datetime.datetime.now())
+ logging.getLogger().setLevel(logging.ERROR)
+
+ # enable logging when member vars are assigned
+ import ibapi.utils as utils
+ from ibapi.order import Order
+
+ Order.__setattr__ = utils.setattr_log
+ from ibapi.contract import Contract, DeltaNeutralContract
+
+ Contract.__setattr__ = utils.setattr_log
+ DeltaNeutralContract.__setattr__ = utils.setattr_log
+ from ibapi.tag_value import TagValue
+
+ TagValue.__setattr__ = utils.setattr_log
+ TimeCondition.__setattr__ = utils.setattr_log
+ ExecutionCondition.__setattr__ = utils.setattr_log
+ MarginCondition.__setattr__ = utils.setattr_log
+ PriceCondition.__setattr__ = utils.setattr_log
+ PercentChangeCondition.__setattr__ = utils.setattr_log
+ VolumeCondition.__setattr__ = utils.setattr_log
+
+ # from inspect import signature as sig
+ # import code; code.interact(local=dict(globals(), **locals()))
+ # sys.exit(1)
+
+ app = TestApp()
+ app.connect("127.0.0.1", args.port, 0)
+
+ app.reqCurrentTime()
+ app.reqManagedAccts()
+ app.reqAccountSummary(reqId=2, groupName="All", tags="NetLiquidation")
+
+ app.reqAllOpenOrders()
+
+ contract = Contract()
+ contract.symbol = "AMD"
+ contract.secType = "STK"
+ contract.currency = "USD"
+ contract.exchange = "SMART"
+ # app.reqMarketDataType(1)
+ # app.reqMktData(1001, contract, "", snapshot=True)
+ # app.cancelMktData(1001)
+ # app.reqExecutions(2001, ExecutionFilter())
+ # app.reqContractDetails(3001, contract)
+ # app.reqPositions()
+ # app.reqIds(2)
+
+ # app.reqMktDepth(4001, contract, 5, "")
+ # app.cancelMktDepth(4001)
+
+ # app.reqNewsBulletins(allMsgs=True)
+ # app.cancelNewsBulletins()
+ # app.requestFA(FaDataTypeEnum.GROUPS)
+
+ # app.reqHistoricalData(5001, contract, "20161215 16:00:00", "2 D",
+ # "1 hour", "TRADES", 0, 1, [])
+ # app.cancelHistoricalData(5001)
+
+ # app.reqFundamentalData(6001, contract, "ReportSnapshot")
+ # app.cancelFundamentalData(6001)
+ # app.queryDisplayGroups(7001)
+ # app.subscribeToGroupEvents(7002, 1)
+ # app.unsubscribeFromGroupEvents(7002)
+
+ # app.reqScannerParameters()
+ ss = ScannerSubscription()
+ ss.instrument = "STK"
+ ss.locationCode = "STK.US"
+ ss.scanCode = "TOP_PERC_LOSE"
+ # app.reqScannerSubscription(8001, ss, [])
+ # app.cancelScannerSubscription(8001)
+ # app.reqRealTimeBars(9001, contract, 5, "TRADES", 0, [])
+ # app.cancelRealTimeBars(9001)
+ # app.reqSecDefOptParams(10001, "AMD", "", "STK", 4391)
+ # app.reqSoftDollarTiers(11001)
+ # app.reqFamilyCodes()
+ # app.reqMatchingSymbols(12001, "AMD")
+
+ contract = Contract()
+ contract.symbol = "AMD"
+ contract.secType = "OPT"
+ contract.exchange = "SMART"
+ contract.currency = "USD"
+ contract.lastTradeDateOrContractMonth = "20170120"
+ contract.strike = 10
+ contract.right = "C"
+ contract.multiplier = "100"
+ # Often, contracts will also require a trading class to rule out ambiguities
+ contract.tradingClass = "AMD"
+ # app.calculateImpliedVolatility(13001, contract, 1.3, 10.85)
+ # app.calculateOptionPrice(13002, contract, 0.65, 10.85)
+
+ app.run()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/packages/ibkr/ref/source/pythonclient/tests/test_account_summary_tags.py b/packages/ibkr/ref/source/pythonclient/tests/test_account_summary_tags.py
new file mode 100644
index 00000000..2108f423
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tests/test_account_summary_tags.py
@@ -0,0 +1,22 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import unittest
+from ibapi.account_summary_tags import AccountSummaryTags
+
+
+class AccountSummaryTagsTestCase(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_all_tags(self):
+ print(AccountSummaryTags.AllTags)
+
+
+if "__main__" == __name__:
+ unittest.main()
diff --git a/packages/ibkr/ref/source/pythonclient/tests/test_comm.py b/packages/ibkr/ref/source/pythonclient/tests/test_comm.py
new file mode 100644
index 00000000..d099e4f4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tests/test_comm.py
@@ -0,0 +1,60 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import unittest
+import struct
+from ibapi import comm
+
+
+class CommTestCase(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_make_msg(self):
+ text = "ABCD"
+ msg = comm.make_initial_msg(text)
+
+ size = struct.unpack("!I", msg[0:4])[0]
+
+ self.assertEqual(size, len(text), "msg size not good")
+ self.assertEqual(msg[4:].decode(), text, "msg payload not good")
+
+ def test_make_field(self):
+ text = "ABCD"
+ field = comm.make_field(text)
+
+ self.assertEqual(field[-1], "\0", "terminator not good")
+ self.assertEqual(len(field[0:-1]), len(text), "payload size not good")
+ self.assertEqual(field[0:-1], text, "payload not good")
+
+ def test_read_msg(self):
+ text = "ABCD"
+ msg = comm.make_initial_msg(text)
+
+ (size, text2, rest) = comm.read_msg(msg)
+
+ self.assertEqual(size, len(text), "msg size not good")
+ self.assertEqual(text2.decode(), text, "msg payload not good")
+ self.assertEqual(len(rest), 0, "there should be no remainder msg")
+
+ def test_readFields(self):
+ text1 = "ABCD"
+ text2 = "123"
+
+ msg = comm.make_initial_msg(comm.make_field(text1) + comm.make_field(text2))
+
+ (size, text, rest) = comm.read_msg(msg)
+ fields = comm.read_fields(text)
+
+ self.assertEqual(len(fields), 2, "incorrect number of fields")
+ self.assertEqual(fields[0].decode(), text1)
+ self.assertEqual(fields[1].decode(), text2)
+
+
+if "__main__" == __name__:
+ unittest.main()
diff --git a/packages/ibkr/ref/source/pythonclient/tests/test_enum_implem.py b/packages/ibkr/ref/source/pythonclient/tests/test_enum_implem.py
new file mode 100644
index 00000000..762ea214
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tests/test_enum_implem.py
@@ -0,0 +1,25 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import unittest
+
+from ibapi.enum_implem import Enum
+
+
+class EnumTestCase(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_enum(self):
+ e = Enum("ZERO", "ONE", "TWO")
+ print(e.ZERO)
+ print(e.toStr(e.ZERO))
+
+
+if "__main__" == __name__:
+ unittest.main()
diff --git a/packages/ibkr/ref/source/pythonclient/tests/test_order_conditions.py b/packages/ibkr/ref/source/pythonclient/tests/test_order_conditions.py
new file mode 100644
index 00000000..1bf044cd
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tests/test_order_conditions.py
@@ -0,0 +1,28 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import unittest
+
+from ibapi.order_condition import *
+
+
+class ConditionOrderTestCase(unittest.TestCase):
+ conds = [
+ VolumeCondition(8314, "SMART", True, 1000000).And(),
+ PercentChangeCondition(1111, "AMEX", True, 0.25).Or(),
+ PriceCondition(
+ PriceCondition.TriggerMethodEnum.DoubleLast, 2222, "NASDAQ", False, 4.75
+ ).And(),
+ TimeCondition(True, "20170101 09:30:00").And(),
+ MarginCondition(False, 200000).Or(),
+ ExecutionCondition("STK", "SMART", "AMD"),
+ ]
+
+ for cond in conds:
+ print(cond, OrderCondition.__str__(cond))
+
+
+if "__main__" == __name__:
+ unittest.main()
diff --git a/packages/ibkr/ref/source/pythonclient/tests/test_utils.py b/packages/ibkr/ref/source/pythonclient/tests/test_utils.py
new file mode 100644
index 00000000..4ef0b0d4
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tests/test_utils.py
@@ -0,0 +1,53 @@
+"""
+Copyright (C) 2019 Interactive Brokers LLC. All rights reserved. This code is subject to the terms
+ and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable.
+"""
+
+import unittest
+
+from ibapi.enum_implem import Enum
+from ibapi.utils import setattr_log
+
+
+class UtilsTestCase(unittest.TestCase):
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_enum(self):
+ e = Enum("ZERO", "ONE", "TWO")
+ print(e.ZERO)
+ print(e.toStr(e.ZERO))
+
+ def test_setattr_log(self):
+ class A:
+ def __init__(self):
+ self.n = 5
+
+ A.__setattr__ = setattr_log
+ a = A()
+ print(a.n)
+ a.n = 6
+ print(a.n)
+
+ def test_polymorphism(self):
+ class A:
+ def __init__(self):
+ self.n = 5
+
+ def m(self):
+ self.n += 1
+
+ class B(A):
+ def m(self):
+ self.n += 2
+
+ o = B()
+ print(o)
+ # import code; code.interact(local=locals())
+
+
+if "__main__" == __name__:
+ unittest.main()
diff --git a/packages/ibkr/ref/source/pythonclient/tox.ini b/packages/ibkr/ref/source/pythonclient/tox.ini
new file mode 100644
index 00000000..118c4ef8
--- /dev/null
+++ b/packages/ibkr/ref/source/pythonclient/tox.ini
@@ -0,0 +1,6 @@
+[tox]
+envlist = py33, py34, py35
+
+[testenv]
+deps = pytest
+commands = py.test {posargs}
diff --git a/packages/ibkr/src/account-summary-tags.ts b/packages/ibkr/src/account-summary-tags.ts
new file mode 100644
index 00000000..c79d41c0
--- /dev/null
+++ b/packages/ibkr/src/account-summary-tags.ts
@@ -0,0 +1,38 @@
+/**
+ * Account summary tag constants.
+ * Mirrors: ibapi/account_summary_tags.py
+ */
+
+export const AccountSummaryTags = {
+ AccountType: 'AccountType',
+ NetLiquidation: 'NetLiquidation',
+ TotalCashValue: 'TotalCashValue',
+ SettledCash: 'SettledCash',
+ AccruedCash: 'AccruedCash',
+ BuyingPower: 'BuyingPower',
+ EquityWithLoanValue: 'EquityWithLoanValue',
+ PreviousDayEquityWithLoanValue: 'PreviousDayEquityWithLoanValue',
+ GrossPositionValue: 'GrossPositionValue',
+ ReqTEquity: 'ReqTEquity',
+ ReqTMargin: 'ReqTMargin',
+ SMA: 'SMA',
+ InitMarginReq: 'InitMarginReq',
+ MaintMarginReq: 'MaintMarginReq',
+ AvailableFunds: 'AvailableFunds',
+ ExcessLiquidity: 'ExcessLiquidity',
+ Cushion: 'Cushion',
+ FullInitMarginReq: 'FullInitMarginReq',
+ FullMaintMarginReq: 'FullMaintMarginReq',
+ FullAvailableFunds: 'FullAvailableFunds',
+ FullExcessLiquidity: 'FullExcessLiquidity',
+ LookAheadNextChange: 'LookAheadNextChange',
+ LookAheadInitMarginReq: 'LookAheadInitMarginReq',
+ LookAheadMaintMarginReq: 'LookAheadMaintMarginReq',
+ LookAheadAvailableFunds: 'LookAheadAvailableFunds',
+ LookAheadExcessLiquidity: 'LookAheadExcessLiquidity',
+ HighestSeverity: 'HighestSeverity',
+ DayTradesRemaining: 'DayTradesRemaining',
+ Leverage: 'Leverage',
+} as const
+
+export const AllTags = Object.values(AccountSummaryTags).join(',')
diff --git a/packages/ibkr/src/client/account.ts b/packages/ibkr/src/client/account.ts
new file mode 100644
index 00000000..6895d429
--- /dev/null
+++ b/packages/ibkr/src/client/account.ts
@@ -0,0 +1,319 @@
+/**
+ * EClient account, positions, executions, contract details methods.
+ * Mirrors: ibapi/client.py lines 3210-4840
+ */
+
+import { EClient } from './base.js'
+import { makeField, makeFieldHandleEmpty } from '../comm.js'
+import { OUT } from '../message.js'
+import * as SV from '../server-versions.js'
+import { NO_VALID_ID, UNSET_INTEGER } from '../const.js'
+import * as errors from '../errors.js'
+import { currentTimeMillis } from '../utils.js'
+import type { Contract } from '../contract.js'
+import type { ExecutionFilter } from '../execution.js'
+
+declare module './base.js' {
+ interface EClient {
+ reqAccountUpdates(subscribe: boolean, acctCode: string): void
+ reqAccountSummary(reqId: number, groupName: string, tags: string): void
+ cancelAccountSummary(reqId: number): void
+ reqPositions(): void
+ cancelPositions(): void
+ reqPositionsMulti(reqId: number, account: string, modelCode: string): void
+ cancelPositionsMulti(reqId: number): void
+ reqAccountUpdatesMulti(reqId: number, account: string, modelCode: string, ledgerAndNLV: boolean): void
+ cancelAccountUpdatesMulti(reqId: number): void
+ reqPnL(reqId: number, account: string, modelCode: string): void
+ cancelPnL(reqId: number): void
+ reqPnLSingle(reqId: number, account: string, modelCode: string, conid: number): void
+ cancelPnLSingle(reqId: number): void
+ reqExecutions(reqId: number, execFilter: ExecutionFilter): void
+ reqContractDetails(reqId: number, contract: Contract): void
+ cancelContractData(reqId: number): void
+ reqMktDepthExchanges(): void
+ reqMktDepth(reqId: number, contract: Contract, numRows: number, isSmartDepth: boolean, mktDepthOptions: unknown): void
+ cancelMktDepth(reqId: number, isSmartDepth: boolean): void
+ reqNewsBulletins(allMsgs: boolean): void
+ cancelNewsBulletins(): void
+ reqManagedAccts(): void
+ requestFA(faData: number): void
+ replaceFA(reqId: number, faData: number, cxml: string): void
+ }
+}
+
+export function applyAccount(Client: typeof EClient): void {
+
+ Client.prototype.reqAccountUpdates = function (this: EClient, subscribe: boolean, acctCode: string): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_ACCT_DATA, makeField(2) + makeField(subscribe) + makeField(acctCode))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_ACCT.code(), errors.FAIL_SEND_ACCT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqAccountSummary = function (this: EClient, reqId: number, groupName: string, tags: string): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_ACCOUNT_SUMMARY, makeField(1) + makeField(reqId) + makeField(groupName) + makeField(tags))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQACCOUNTDATA.code(), errors.FAIL_SEND_REQACCOUNTDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelAccountSummary = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_ACCOUNT_SUMMARY, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANACCOUNTDATA.code(), errors.FAIL_SEND_CANACCOUNTDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqPositions = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_POSITIONS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQPOSITIONS.code(), errors.FAIL_SEND_REQPOSITIONS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelPositions = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_POSITIONS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_CANPOSITIONS.code(), errors.FAIL_SEND_CANPOSITIONS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqPositionsMulti = function (this: EClient, reqId: number, account: string, modelCode: string): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_POSITIONS_MULTI, makeField(1) + makeField(reqId) + makeField(account) + makeField(modelCode))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQPOSITIONSMULTI.code(), errors.FAIL_SEND_REQPOSITIONSMULTI.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelPositionsMulti = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_POSITIONS_MULTI, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANPOSITIONSMULTI.code(), errors.FAIL_SEND_CANPOSITIONSMULTI.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqAccountUpdatesMulti = function (this: EClient, reqId: number, account: string, modelCode: string, ledgerAndNLV: boolean): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_ACCOUNT_UPDATES_MULTI, makeField(1) + makeField(reqId) + makeField(account) + makeField(modelCode) + makeField(ledgerAndNLV))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQACCOUNTUPDATESMULTI.code(), errors.FAIL_SEND_REQACCOUNTUPDATESMULTI.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelAccountUpdatesMulti = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_ACCOUNT_UPDATES_MULTI, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANACCOUNTUPDATESMULTI.code(), errors.FAIL_SEND_CANACCOUNTUPDATESMULTI.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqPnL = function (this: EClient, reqId: number, account: string, modelCode: string): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_PNL, makeField(reqId) + makeField(account) + makeField(modelCode))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQPNL.code(), errors.FAIL_SEND_REQPNL.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelPnL = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_PNL, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCELPNL.code(), errors.FAIL_SEND_CANCELPNL.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqPnLSingle = function (this: EClient, reqId: number, account: string, modelCode: string, conid: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_PNL_SINGLE, makeField(reqId) + makeField(account) + makeField(modelCode) + makeField(conid))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQPNLSINGLE.code(), errors.FAIL_SEND_REQPNLSINGLE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelPnLSingle = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_PNL_SINGLE, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCELPNLSINGLE.code(), errors.FAIL_SEND_CANCELPNLSINGLE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqExecutions = function (this: EClient, reqId: number, execFilter: ExecutionFilter): void {
+ if (!this.requireConnected()) return
+ try {
+ const flds = [makeField(3)]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_EXECUTION_DATA_CHAIN) flds.push(makeField(reqId))
+ flds.push(
+ makeField(execFilter.clientId), makeField(execFilter.acctCode), makeField(execFilter.time),
+ makeField(execFilter.symbol), makeField(execFilter.secType), makeField(execFilter.exchange),
+ makeField(execFilter.side),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PARAMETRIZED_DAYS_OF_EXECUTIONS) {
+ flds.push(makeField(execFilter.lastNDays))
+ if (execFilter.specificDates != null) {
+ flds.push(makeField(execFilter.specificDates.length))
+ for (const d of execFilter.specificDates) flds.push(makeField(d))
+ } else {
+ flds.push(makeField(0))
+ }
+ }
+ this.sendMsg(OUT.REQ_EXECUTIONS, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_EXEC.code(), errors.FAIL_SEND_EXEC.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqContractDetails = function (this: EClient, reqId: number, contract: Contract): void {
+ if (!this.requireConnected()) return
+ try {
+ const flds = [makeField(8)]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CONTRACT_DATA_CHAIN) flds.push(makeField(reqId))
+ flds.push(
+ makeField(contract.conId), makeField(contract.symbol), makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth), makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right), makeField(contract.multiplier),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PRIMARYEXCH) {
+ flds.push(makeField(contract.exchange), makeField(contract.primaryExchange))
+ } else if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ if (contract.primaryExchange && (contract.exchange === 'BEST' || contract.exchange === 'SMART')) {
+ flds.push(makeField(contract.exchange + ':' + contract.primaryExchange))
+ } else {
+ flds.push(makeField(contract.exchange))
+ }
+ }
+ flds.push(makeField(contract.currency), makeField(contract.localSymbol))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.tradingClass))
+ flds.push(makeField(contract.includeExpired))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SEC_ID_TYPE) flds.push(makeField(contract.secIdType), makeField(contract.secId))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_BOND_ISSUERID) flds.push(makeField(contract.issuerId))
+ this.sendMsg(OUT.REQ_CONTRACT_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQCONTRACT.code(), errors.FAIL_SEND_REQCONTRACT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelContractData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_CONTRACT_DATA, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCEL_CONTRACT_DATA.code(), errors.FAIL_SEND_CANCEL_CONTRACT_DATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqMktDepthExchanges = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_MKT_DEPTH_EXCHANGES, '')
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQMKTDEPTHEXCHANGES.code(), errors.FAIL_SEND_REQMKTDEPTHEXCHANGES.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqMktDepth = function (
+ this: EClient, reqId: number, contract: Contract, numRows: number,
+ isSmartDepth: boolean, _mktDepthOptions: unknown,
+ ): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ const flds = [makeField(5), makeField(reqId)]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.conId))
+ flds.push(
+ makeField(contract.symbol), makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth), makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right), makeField(contract.multiplier), makeField(contract.exchange),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_MKT_DEPTH_PRIM_EXCHANGE) flds.push(makeField(contract.primaryExchange))
+ flds.push(makeField(contract.currency), makeField(contract.localSymbol))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.tradingClass))
+ flds.push(makeField(numRows))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SMART_DEPTH) flds.push(makeField(isSmartDepth))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) flds.push(makeField(''))
+ this.sendMsg(OUT.REQ_MKT_DEPTH, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQMKTDEPTH.code(), errors.FAIL_SEND_REQMKTDEPTH.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelMktDepth = function (this: EClient, reqId: number, isSmartDepth: boolean): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ const flds = [makeField(1), makeField(reqId)]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SMART_DEPTH) flds.push(makeField(isSmartDepth))
+ this.sendMsg(OUT.CANCEL_MKT_DEPTH, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANMKTDEPTH.code(), errors.FAIL_SEND_CANMKTDEPTH.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqNewsBulletins = function (this: EClient, allMsgs: boolean): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_NEWS_BULLETINS, makeField(1) + makeField(allMsgs))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQMKT.code(), errors.FAIL_SEND_REQMKT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelNewsBulletins = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_NEWS_BULLETINS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQMKT.code(), errors.FAIL_SEND_REQMKT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqManagedAccts = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_MANAGED_ACCTS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQMKT.code(), errors.FAIL_SEND_REQMKT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.requestFA = function (this: EClient, faData: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_FA, makeField(1) + makeField(faData))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_FA_REQUEST.code(), errors.FAIL_SEND_FA_REQUEST.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.replaceFA = function (this: EClient, reqId: number, faData: number, cxml: string): void {
+ if (!this.requireConnected()) return
+ try {
+ const flds = [makeField(1), makeField(faData), makeField(cxml)]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_REPLACE_FA_END) flds.push(makeField(reqId))
+ this.sendMsg(OUT.REPLACE_FA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_FA_REPLACE.code(), errors.FAIL_SEND_FA_REPLACE.msg() + String(ex))
+ }
+ }
+}
diff --git a/packages/ibkr/src/client/base.ts b/packages/ibkr/src/client/base.ts
new file mode 100644
index 00000000..506f8f03
--- /dev/null
+++ b/packages/ibkr/src/client/base.ts
@@ -0,0 +1,302 @@
+/**
+ * EClient base class — connection management, handshake, sendMsg.
+ * Mirrors: ibapi/client.py (lines 286-626)
+ *
+ * Request methods are added via mixins in sibling files.
+ */
+
+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 type { EWrapper } from '../wrapper.js'
+import { OUT } from '../message.js'
+import {
+ MIN_CLIENT_VER,
+ MAX_CLIENT_VER,
+ MIN_SERVER_VER_OPTIONAL_CAPABILITIES,
+ MIN_SERVER_VER_PROTOBUF,
+} from '../server-versions.js'
+import { NO_VALID_ID } from '../const.js'
+import { PROTOBUF_MSG_IDS } from '../common.js'
+import * as errors from '../errors.js'
+import { ClientException, isAsciiPrintable, currentTimeMillis } from '../utils.js'
+
+export class EClient {
+ static readonly DISCONNECTED = 0
+ static readonly CONNECTING = 1
+ static readonly CONNECTED = 2
+
+ wrapper: EWrapper
+ decoder: Decoder | null = null
+ conn: Connection | null = null
+ host: string | null = null
+ port: number | null = null
+ extraAuth = false
+ clientId: number | null = null
+ serverVersion_: number | null = null
+ connTime: string | null = null
+ connState: number = EClient.DISCONNECTED
+ optCapab: string | null = null
+ reader: EReader | null = null
+ connectOptions: string | null = null
+
+ constructor(wrapper: EWrapper) {
+ this.wrapper = wrapper
+ }
+
+ reset(): void {
+ this.conn = null
+ this.host = null
+ this.port = null
+ this.extraAuth = false
+ this.clientId = null
+ this.serverVersion_ = null
+ this.connTime = null
+ this.optCapab = null
+ this.reader = null
+ this.setConnState(EClient.DISCONNECTED)
+ this.connectOptions = null
+ }
+
+ setConnState(connState: number): void {
+ this.connState = connState
+ }
+
+ sendMsg(msgId: number, msg: string): void {
+ const useRawIntMsgId = this.serverVersion() >= MIN_SERVER_VER_PROTOBUF
+ const fullMsg = makeMsg(msgId, useRawIntMsgId, msg)
+ this.conn!.sendMsg(fullMsg)
+ }
+
+ sendMsgProtoBuf(msgId: number, msg: Buffer): void {
+ const fullMsg = makeMsgProto(msgId, msg)
+ this.conn!.sendMsg(fullMsg)
+ }
+
+ checkConnected(): void {
+ if (this.isConnected()) {
+ throw new ClientException(
+ errors.ALREADY_CONNECTED.code(),
+ errors.ALREADY_CONNECTED.msg(),
+ '',
+ )
+ }
+ }
+
+ useProtoBuf(msgId: number): boolean {
+ const unifiedVersion = PROTOBUF_MSG_IDS[msgId]
+ return unifiedVersion !== undefined && unifiedVersion <= this.serverVersion()
+ }
+
+ serverVersion(): number {
+ return this.serverVersion_ ?? 0
+ }
+
+ twsConnectionTime(): string | null {
+ return this.connTime
+ }
+
+ isConnected(): boolean {
+ const connConnected = this.conn?.isConnected() ?? false
+ return this.connState === EClient.CONNECTED && connConnected
+ }
+
+ setConnectOptions(opts: string): void {
+ this.connectOptions = opts
+ }
+
+ setOptionalCapabilities(optCapab: string): void {
+ this.optCapab = optCapab
+ }
+
+ // ── Connect / Disconnect ────────────────────────────────────────────
+
+ async connect(host: string, port: number, clientId: number): Promise {
+ try {
+ this.validateInvalidSymbols(host)
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg + ex.text)
+ return
+ }
+
+ try {
+ this.checkConnected()
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), ex.code, ex.msg)
+ return
+ }
+
+ try {
+ this.host = host
+ this.port = port
+ this.clientId = clientId
+
+ this.conn = new Connection(this.host, this.port)
+ this.conn.wrapper = this.wrapper as any
+
+ await this.conn.connect()
+ this.setConnState(EClient.CONNECTING)
+
+ // Send handshake: "API\0" + version range
+ const v100prefix = 'API\0'
+ let v100version = `v${MIN_CLIENT_VER}..${MAX_CLIENT_VER}`
+ if (this.connectOptions) {
+ v100version = v100version + ' ' + this.connectOptions
+ }
+
+ const msg = makeInitialMsg(v100version)
+ const msg2 = Buffer.concat([Buffer.from(v100prefix, 'ascii'), msg])
+ this.conn.sendMsg(msg2)
+
+ // Wait for server version response
+ const { serverVersion, connTime } = await this.waitForHandshake()
+ this.serverVersion_ = serverVersion
+ this.connTime = connTime
+
+ this.decoder = new Decoder(this.wrapper, this.serverVersion())
+ applyAllHandlers(this.decoder)
+ this.setConnState(EClient.CONNECTED)
+
+ // Start reader
+ this.reader = new EReader(this.conn, (msgBuf: Buffer) => {
+ this.onMessage(msgBuf)
+ })
+ this.reader.start()
+
+ // Send startApi
+ this.startApi()
+ this.wrapper.connectAck()
+ } catch {
+ if (this.wrapper) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.CONNECT_FAIL.code(), errors.CONNECT_FAIL.msg())
+ }
+ this.disconnect()
+ }
+ }
+
+ disconnect(): void {
+ this.setConnState(EClient.DISCONNECTED)
+ if (this.conn !== null) {
+ this.conn.disconnect()
+ this.wrapper.connectionClosed()
+ this.reset()
+ }
+ }
+
+ // ── StartApi ────────────────────────────────────────────────────────
+
+ startApi(): void {
+ if (!this.isConnected()) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.NOT_CONNECTED.code(), errors.NOT_CONNECTED.msg())
+ return
+ }
+
+ try {
+ const VERSION = 2
+ let msg = makeField(VERSION) + makeField(this.clientId)
+ if (this.serverVersion() >= MIN_SERVER_VER_OPTIONAL_CAPABILITIES) {
+ msg += makeField(this.optCapab ?? '')
+ }
+ this.sendMsg(OUT.START_API, msg)
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_STARTAPI.code(), errors.FAIL_SEND_STARTAPI.msg() + String(ex))
+ }
+ }
+
+ // ── Internal helpers ────────────────────────────────────────────────
+
+ /** Check that the connection is live; if not, report error and return false. */
+ protected requireConnected(reqId: number = NO_VALID_ID): boolean {
+ if (!this.isConnected()) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.NOT_CONNECTED.code(), errors.NOT_CONNECTED.msg())
+ return false
+ }
+ return true
+ }
+
+ private validateInvalidSymbols(host: string): void {
+ if (host && !isAsciiPrintable(host)) {
+ throw new ClientException(errors.INVALID_SYMBOL.code(), errors.INVALID_SYMBOL.msg(), host)
+ }
+ if (this.connectOptions && !isAsciiPrintable(this.connectOptions)) {
+ throw new ClientException(errors.INVALID_SYMBOL.code(), errors.INVALID_SYMBOL.msg(), this.connectOptions)
+ }
+ if (this.optCapab && !isAsciiPrintable(this.optCapab)) {
+ throw new ClientException(errors.INVALID_SYMBOL.code(), errors.INVALID_SYMBOL.msg(), this.optCapab)
+ }
+ }
+
+ /**
+ * Process a single framed message from the reader.
+ * Mirrors: ibapi/client.py run() lines 595-611
+ *
+ * Server v201+: 4-byte big-endian binary msgId prefix.
+ * If msgId > PROTOBUF_MSG_ID (200) → protobuf (subtract 200 for real msgId).
+ * Otherwise → text with \0-delimited fields.
+ *
+ * Server < 201: text msgId is first \0-delimited field.
+ */
+ private onMessage(msgBuf: Buffer): void {
+ if (!this.decoder) return
+
+ const PROTOBUF_MSG_ID = 200
+ let msgId: number
+ let payload: Buffer
+
+ if (this.serverVersion() >= MIN_SERVER_VER_PROTOBUF) {
+ // v201+: first 4 bytes are binary msgId
+ msgId = msgBuf.readUInt32BE(0)
+ payload = msgBuf.subarray(4)
+ } else {
+ // Legacy: first \0-delimited field is the text msgId
+ const nullIdx = msgBuf.indexOf(0)
+ if (nullIdx < 0) return
+ msgId = parseInt(msgBuf.subarray(0, nullIdx).toString('utf-8'), 10)
+ payload = msgBuf.subarray(nullIdx + 1)
+ }
+
+ if (msgId > PROTOBUF_MSG_ID) {
+ // Protobuf message
+ msgId -= PROTOBUF_MSG_ID
+ this.decoder.processProtoBuf(payload, msgId)
+ } else {
+ // Text message — split into fields and dispatch
+ const fields = readFields(payload)
+ this.decoder.interpret(fields, msgId)
+ }
+ }
+
+ private waitForHandshake(): Promise<{ serverVersion: number; connTime: string }> {
+ return new Promise((resolve, reject) => {
+ let buf: Buffer = Buffer.alloc(0)
+
+ const onData = () => {
+ const incoming = this.conn!.consumeBuffer()
+ if (incoming.length === 0) return
+
+ buf = Buffer.concat([buf, incoming])
+ const [size, msg, rest] = readMsg(buf)
+ if (msg.length > 0) {
+ buf = rest
+ const fields = readFields(msg)
+ if (fields.length >= 2) {
+ this.conn!.removeListener('data', onData)
+ resolve({
+ serverVersion: parseInt(fields[0], 10),
+ connTime: fields[1],
+ })
+ }
+ }
+ }
+
+ this.conn!.on('data', onData)
+
+ // Timeout after 10 seconds
+ setTimeout(() => {
+ this.conn!.removeListener('data', onData)
+ reject(new Error('Handshake timeout'))
+ }, 10000)
+ })
+ }
+}
diff --git a/packages/ibkr/src/client/encode.ts b/packages/ibkr/src/client/encode.ts
new file mode 100644
index 00000000..6591197d
--- /dev/null
+++ b/packages/ibkr/src/client/encode.ts
@@ -0,0 +1,74 @@
+/**
+ * Shared encoding helpers for client request methods.
+ * Reduces duplication across market-data, orders, account, historical.
+ */
+
+import { makeField, makeFieldHandleEmpty } from '../comm.js'
+import type { Contract } from '../contract.js'
+import type { EClient } from './base.js'
+import * as SV from '../server-versions.js'
+
+/**
+ * Encode the standard contract fields used by most request methods.
+ * Returns array of makeField() strings ready to join.
+ */
+export function encodeContract(client: EClient, contract: Contract, includeConId = true): string[] {
+ const flds: string[] = []
+
+ if (includeConId) {
+ flds.push(makeField(contract.conId))
+ }
+
+ flds.push(
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ )
+
+ if (client.serverVersion() >= SV.MIN_SERVER_VER_PRIMARYEXCH) {
+ flds.push(makeField(contract.primaryExchange))
+ }
+
+ flds.push(
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ )
+
+ if (client.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.tradingClass))
+ }
+
+ return flds
+}
+
+/**
+ * Encode contract fields in the "legacy" order (primaryExchange always included,
+ * no version gate). Used by some older-style methods.
+ */
+export function encodeContractLegacy(client: EClient, contract: Contract): string[] {
+ const flds: string[] = []
+
+ flds.push(
+ makeField(contract.conId),
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ )
+
+ if (client.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.tradingClass))
+ }
+
+ return flds
+}
diff --git a/packages/ibkr/src/client/historical.ts b/packages/ibkr/src/client/historical.ts
new file mode 100644
index 00000000..720d9023
--- /dev/null
+++ b/packages/ibkr/src/client/historical.ts
@@ -0,0 +1,997 @@
+/**
+ * EClient mixin — historical data, scanner, news, and misc methods.
+ * Mirrors: ibapi/client.py (lines ~4842-7500)
+ *
+ * Applied via applyHistorical() which extends EClient.prototype.
+ */
+
+import { EClient } from './base.js'
+import { makeField, makeFieldHandleEmpty } from '../comm.js'
+import { OUT } from '../message.js'
+import * as SV from '../server-versions.js'
+import { NO_VALID_ID, UNSET_INTEGER } from '../const.js'
+import * as errors from '../errors.js'
+import { currentTimeMillis } from '../utils.js'
+import type { Contract } from '../contract.js'
+import type { ScannerSubscription } from '../scanner.js'
+import type { TagValueList } from '../tag-value.js'
+import type { WshEventData } from '../common.js'
+
+declare module './base.js' {
+ interface EClient {
+ reqHistoricalData(reqId: number, contract: Contract, endDateTime: string, durationStr: string, barSizeSetting: string, whatToShow: string, useRTH: number, formatDate: number, keepUpToDate: boolean, chartOptions: TagValueList): void
+ cancelHistoricalData(reqId: number): void
+ reqHeadTimeStamp(reqId: number, contract: Contract, whatToShow: string, useRTH: number, formatDate: number): void
+ cancelHeadTimeStamp(reqId: number): void
+ reqHistogramData(tickerId: number, contract: Contract, useRTH: boolean, timePeriod: string): void
+ cancelHistogramData(tickerId: number): void
+ reqHistoricalTicks(reqId: number, contract: Contract, startDateTime: string, endDateTime: string, numberOfTicks: number, whatToShow: string, useRth: number, ignoreSize: boolean, miscOptions: TagValueList): void
+ reqScannerParameters(): void
+ reqScannerSubscription(reqId: number, subscription: ScannerSubscription, scannerSubscriptionOptions: TagValueList, scannerSubscriptionFilterOptions: TagValueList): void
+ cancelScannerSubscription(reqId: number): void
+ reqRealTimeBars(reqId: number, contract: Contract, barSize: number, whatToShow: string, useRTH: boolean, realTimeBarsOptions: TagValueList): void
+ cancelRealTimeBars(reqId: number): void
+ reqFundamentalData(reqId: number, contract: Contract, reportType: string, fundamentalDataOptions: TagValueList): void
+ cancelFundamentalData(reqId: number): void
+ reqNewsProviders(): void
+ reqNewsArticle(reqId: number, providerCode: string, articleId: string, newsArticleOptions: TagValueList): void
+ reqHistoricalNews(reqId: number, conId: number, providerCodes: string, startDateTime: string, endDateTime: string, totalResults: number, historicalNewsOptions: TagValueList): void
+ queryDisplayGroups(reqId: number): void
+ subscribeToGroupEvents(reqId: number, groupId: number): void
+ updateDisplayGroup(reqId: number, contractInfo: string): void
+ unsubscribeFromGroupEvents(reqId: number): void
+ verifyRequest(apiName: string, apiVersion: string): void
+ verifyMessage(apiData: string): void
+ verifyAndAuthRequest(apiName: string, apiVersion: string, opaqueIsvKey: string): void
+ verifyAndAuthMessage(apiData: string, xyzResponse: string): void
+ reqSecDefOptParams(reqId: number, underlyingSymbol: string, futFopExchange: string, underlyingSecType: string, underlyingConId: number): void
+ reqSoftDollarTiers(reqId: number): void
+ reqFamilyCodes(): void
+ reqMatchingSymbols(reqId: number, pattern: string): void
+ reqWshMetaData(reqId: number): void
+ cancelWshMetaData(reqId: number): void
+ reqWshEventData(reqId: number, wshEventData: WshEventData): void
+ cancelWshEventData(reqId: number): void
+ reqUserInfo(reqId: number): void
+ cancelContractData(reqId: number): void
+ cancelHistoricalTicks(reqId: number): void
+ }
+}
+
+/** Helper: serialize a TagValueList into a wire string. */
+function tagValueListToStr(list: TagValueList): string {
+ if (!list) return ''
+ let s = ''
+ for (const tv of list) {
+ s += String(tv)
+ }
+ return s
+}
+
+export function applyHistorical(Client: typeof EClient): void {
+
+ // ─── Historical Data ───────────────────────────────────────────────
+
+ Client.prototype.reqHistoricalData = function (
+ this: EClient, reqId: number, contract: Contract, endDateTime: string,
+ durationStr: string, barSizeSetting: string, whatToShow: string,
+ useRTH: number, formatDate: number, keepUpToDate: boolean,
+ chartOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected(reqId)) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_TRADING_CLASS) {
+ if (contract.tradingClass || contract.conId > 0) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support conId and tradingClass parameters in reqHistoricalData.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_HISTORICAL_SCHEDULE) {
+ if (whatToShow === 'SCHEDULE') {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support requesting of historical schedule.')
+ return
+ }
+ }
+
+ try {
+ const VERSION = 6
+ const flds: string[] = []
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SYNT_REALTIME_BARS) {
+ flds.push(makeField(VERSION))
+ }
+
+ flds.push(makeField(reqId))
+
+ // contract fields
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.conId))
+ }
+ flds.push(
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.tradingClass))
+ }
+ flds.push(
+ makeField(contract.includeExpired),
+ makeField(endDateTime),
+ makeField(barSizeSetting),
+ makeField(durationStr),
+ makeField(useRTH),
+ makeField(whatToShow),
+ makeField(formatDate),
+ )
+
+ // combo legs for BAG
+ if (contract.secType === 'BAG') {
+ const comboLegsCount = contract.comboLegs?.length ?? 0
+ flds.push(makeField(comboLegsCount))
+ if (contract.comboLegs) {
+ for (const leg of contract.comboLegs) {
+ flds.push(makeField(leg.conId), makeField(leg.ratio), makeField(leg.action), makeField(leg.exchange))
+ }
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SYNT_REALTIME_BARS) {
+ flds.push(makeField(keepUpToDate))
+ }
+
+ // chartOptions
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ flds.push(makeField(tagValueListToStr(chartOptions)))
+ }
+
+ this.sendMsg(OUT.REQ_HISTORICAL_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQHISTDATA.code(), errors.FAIL_SEND_REQHISTDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelHistoricalData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_HISTORICAL_DATA, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANHISTDATA.code(), errors.FAIL_SEND_CANHISTDATA.msg() + String(ex))
+ }
+ }
+
+ // ─── Head Time Stamp ───────────────────────────────────────────────
+
+ Client.prototype.reqHeadTimeStamp = function (
+ this: EClient, reqId: number, contract: Contract,
+ whatToShow: string, useRTH: number, formatDate: number,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_HEAD_TIMESTAMP) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support head time stamp requests.')
+ return
+ }
+
+ try {
+ const flds = [
+ makeField(reqId),
+ makeField(contract.conId),
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ makeField(contract.tradingClass),
+ makeField(contract.includeExpired),
+ makeField(useRTH),
+ makeField(whatToShow),
+ makeField(formatDate),
+ ]
+ this.sendMsg(OUT.REQ_HEAD_TIMESTAMP, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQHEADTIMESTAMP.code(), errors.FAIL_SEND_REQHEADTIMESTAMP.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelHeadTimeStamp = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CANCEL_HEADTIMESTAMP) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support head time stamp requests.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_HEAD_TIMESTAMP, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_CANCELHEADTIMESTAMP.code(), errors.FAIL_SEND_CANCELHEADTIMESTAMP.msg() + String(ex))
+ }
+ }
+
+ // ─── Histogram Data ────────────────────────────────────────────────
+
+ Client.prototype.reqHistogramData = function (
+ this: EClient, tickerId: number, contract: Contract,
+ useRTH: boolean, timePeriod: string,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_HISTOGRAM) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support histogram requests..')
+ return
+ }
+
+ try {
+ const flds = [
+ makeField(tickerId),
+ makeField(contract.conId),
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ makeField(contract.tradingClass),
+ makeField(contract.includeExpired),
+ makeField(useRTH),
+ makeField(timePeriod),
+ ]
+ this.sendMsg(OUT.REQ_HISTOGRAM_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(tickerId, currentTimeMillis(), errors.FAIL_SEND_REQHISTOGRAMDATA.code(), errors.FAIL_SEND_REQHISTOGRAMDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelHistogramData = function (this: EClient, tickerId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_HISTOGRAM) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support histogram requests..')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_HISTOGRAM_DATA, makeField(tickerId))
+ } catch (ex: any) {
+ this.wrapper.error(tickerId, currentTimeMillis(), errors.FAIL_SEND_CANCELHISTOGRAMDATA.code(), errors.FAIL_SEND_CANCELHISTOGRAMDATA.msg() + String(ex))
+ }
+ }
+
+ // ─── Historical Ticks ──────────────────────────────────────────────
+
+ Client.prototype.reqHistoricalTicks = function (
+ this: EClient, reqId: number, contract: Contract,
+ startDateTime: string, endDateTime: string, numberOfTicks: number,
+ whatToShow: string, useRth: number, ignoreSize: boolean,
+ miscOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_HISTORICAL_TICKS) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support historical ticks requests..')
+ return
+ }
+
+ try {
+ const flds = [
+ makeField(reqId),
+ makeField(contract.conId),
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ makeField(contract.tradingClass),
+ makeField(contract.includeExpired),
+ makeField(startDateTime),
+ makeField(endDateTime),
+ makeField(numberOfTicks),
+ makeField(whatToShow),
+ makeField(useRth),
+ makeField(ignoreSize),
+ makeField(tagValueListToStr(miscOptions)),
+ ]
+
+ this.sendMsg(OUT.REQ_HISTORICAL_TICKS, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQHISTORICALTICKS.code(), errors.FAIL_SEND_REQHISTORICALTICKS.msg() + String(ex))
+ }
+ }
+
+ // ─── Market Scanners ───────────────────────────────────────────────
+
+ Client.prototype.reqScannerParameters = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_SCANNER_PARAMETERS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQSCANNERPARAMETERS.code(), errors.FAIL_SEND_REQSCANNERPARAMETERS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqScannerSubscription = function (
+ this: EClient, reqId: number, subscription: ScannerSubscription,
+ scannerSubscriptionOptions: TagValueList,
+ scannerSubscriptionFilterOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SCANNER_GENERIC_OPTS && scannerSubscriptionFilterOptions != null) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support API scanner subscription generic filter options')
+ return
+ }
+
+ try {
+ const VERSION = 4
+ const flds: string[] = []
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SCANNER_GENERIC_OPTS) {
+ flds.push(makeField(VERSION))
+ }
+
+ flds.push(
+ makeField(reqId),
+ makeFieldHandleEmpty(subscription.numberOfRows),
+ makeField(subscription.instrument),
+ makeField(subscription.locationCode),
+ makeField(subscription.scanCode),
+ makeFieldHandleEmpty(subscription.abovePrice),
+ makeFieldHandleEmpty(subscription.belowPrice),
+ makeFieldHandleEmpty(subscription.aboveVolume),
+ makeFieldHandleEmpty(subscription.marketCapAbove),
+ makeFieldHandleEmpty(subscription.marketCapBelow),
+ makeField(subscription.moodyRatingAbove),
+ makeField(subscription.moodyRatingBelow),
+ makeField(subscription.spRatingAbove),
+ makeField(subscription.spRatingBelow),
+ makeField(subscription.maturityDateAbove),
+ makeField(subscription.maturityDateBelow),
+ makeFieldHandleEmpty(subscription.couponRateAbove),
+ makeFieldHandleEmpty(subscription.couponRateBelow),
+ makeField(subscription.excludeConvertible),
+ makeFieldHandleEmpty(subscription.averageOptionVolumeAbove),
+ makeField(subscription.scannerSettingPairs),
+ makeField(subscription.stockTypeFilter),
+ )
+
+ // scannerSubscriptionFilterOptions
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SCANNER_GENERIC_OPTS) {
+ flds.push(makeField(tagValueListToStr(scannerSubscriptionFilterOptions)))
+ }
+
+ // scannerSubscriptionOptions
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ flds.push(makeField(tagValueListToStr(scannerSubscriptionOptions)))
+ }
+
+ this.sendMsg(OUT.REQ_SCANNER_SUBSCRIPTION, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQSCANNER.code(), errors.FAIL_SEND_REQSCANNER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelScannerSubscription = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_SCANNER_SUBSCRIPTION, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANSCANNER.code(), errors.FAIL_SEND_CANSCANNER.msg() + String(ex))
+ }
+ }
+
+ // ─── Real Time Bars ────────────────────────────────────────────────
+
+ Client.prototype.reqRealTimeBars = function (
+ this: EClient, reqId: number, contract: Contract, barSize: number,
+ whatToShow: string, useRTH: boolean, realTimeBarsOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_TRADING_CLASS) {
+ if (contract.tradingClass) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support conId and tradingClass parameter in reqRealTimeBars.')
+ return
+ }
+ }
+
+ try {
+ const VERSION = 3
+ const flds: string[] = [makeField(VERSION), makeField(reqId)]
+
+ // contract fields
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.conId))
+ }
+ flds.push(
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.tradingClass))
+ }
+ flds.push(makeField(barSize), makeField(whatToShow), makeField(useRTH))
+
+ // realTimeBarsOptions
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ flds.push(makeField(tagValueListToStr(realTimeBarsOptions)))
+ }
+
+ this.sendMsg(OUT.REQ_REAL_TIME_BARS, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQRTBARS.code(), errors.FAIL_SEND_REQRTBARS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelRealTimeBars = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ this.sendMsg(OUT.CANCEL_REAL_TIME_BARS, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANRTBARS.code(), errors.FAIL_SEND_CANRTBARS.msg() + String(ex))
+ }
+ }
+
+ // ─── Fundamental Data ──────────────────────────────────────────────
+
+ Client.prototype.reqFundamentalData = function (
+ this: EClient, reqId: number, contract: Contract,
+ reportType: string, fundamentalDataOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_FUNDAMENTAL_DATA) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support fundamental data request.')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_TRADING_CLASS) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support conId parameter in reqFundamentalData.')
+ return
+ }
+
+ try {
+ const VERSION = 2
+ const flds: string[] = [makeField(VERSION), makeField(reqId)]
+
+ // contract fields (no strike, no lastTradeDate, no right, no multiplier — fundamental data specific)
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.conId))
+ }
+ flds.push(
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ makeField(reportType),
+ )
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ const tagValuesCount = fundamentalDataOptions?.length ?? 0
+ flds.push(makeField(tagValuesCount), makeField(tagValueListToStr(fundamentalDataOptions)))
+ }
+
+ this.sendMsg(OUT.REQ_FUNDAMENTAL_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQFUNDDATA.code(), errors.FAIL_SEND_REQFUNDDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelFundamentalData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_FUNDAMENTAL_DATA) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support fundamental data request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_FUNDAMENTAL_DATA, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANFUNDDATA.code(), errors.FAIL_SEND_CANFUNDDATA.msg() + String(ex))
+ }
+ }
+
+ // ─── News ──────────────────────────────────────────────────────────
+
+ Client.prototype.reqNewsProviders = function (this: EClient): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_NEWS_PROVIDERS) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support news providers request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.REQ_NEWS_PROVIDERS, '')
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQNEWSPROVIDERS.code(), errors.FAIL_SEND_REQNEWSPROVIDERS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqNewsArticle = function (
+ this: EClient, reqId: number, providerCode: string,
+ articleId: string, newsArticleOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_NEWS_ARTICLE) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support news article request.')
+ return
+ }
+
+ try {
+ const flds = [
+ makeField(reqId),
+ makeField(providerCode),
+ makeField(articleId),
+ ]
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_NEWS_QUERY_ORIGINS) {
+ flds.push(makeField(tagValueListToStr(newsArticleOptions)))
+ }
+
+ this.sendMsg(OUT.REQ_NEWS_ARTICLE, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQNEWSARTICLE.code(), errors.FAIL_SEND_REQNEWSARTICLE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqHistoricalNews = function (
+ this: EClient, reqId: number, conId: number, providerCodes: string,
+ startDateTime: string, endDateTime: string, totalResults: number,
+ historicalNewsOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_HISTORICAL_NEWS) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support historical news request.')
+ return
+ }
+
+ try {
+ const flds = [
+ makeField(reqId),
+ makeField(conId),
+ makeField(providerCodes),
+ makeField(startDateTime),
+ makeField(endDateTime),
+ makeField(totalResults),
+ ]
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_NEWS_QUERY_ORIGINS) {
+ flds.push(makeField(tagValueListToStr(historicalNewsOptions)))
+ }
+
+ this.sendMsg(OUT.REQ_HISTORICAL_NEWS, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQHISTORICALNEWS.code(), errors.FAIL_SEND_REQHISTORICALNEWS.msg() + String(ex))
+ }
+ }
+
+ // ─── Display Groups ────────────────────────────────────────────────
+
+ Client.prototype.queryDisplayGroups = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support queryDisplayGroups request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.QUERY_DISPLAY_GROUPS, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_QUERYDISPLAYGROUPS.code(), errors.FAIL_SEND_QUERYDISPLAYGROUPS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.subscribeToGroupEvents = function (this: EClient, reqId: number, groupId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support subscribeToGroupEvents request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.SUBSCRIBE_TO_GROUP_EVENTS, makeField(1) + makeField(reqId) + makeField(groupId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_SUBSCRIBETOGROUPEVENTS.code(), errors.FAIL_SEND_SUBSCRIBETOGROUPEVENTS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.updateDisplayGroup = function (this: EClient, reqId: number, contractInfo: string): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support updateDisplayGroup request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.UPDATE_DISPLAY_GROUP, makeField(1) + makeField(reqId) + makeField(contractInfo))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_UPDATEDISPLAYGROUP.code(), errors.FAIL_SEND_UPDATEDISPLAYGROUP.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.unsubscribeFromGroupEvents = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support unsubscribeFromGroupEvents request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.UNSUBSCRIBE_FROM_GROUP_EVENTS, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS.code(), errors.FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS.msg() + String(ex))
+ }
+ }
+
+ // ─── Verification ──────────────────────────────────────────────────
+
+ Client.prototype.verifyRequest = function (this: EClient, apiName: string, apiVersion: string): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support verification request.')
+ return
+ }
+
+ if (!this.extraAuth) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_VERIFYMESSAGE.code(),
+ errors.FAIL_SEND_VERIFYMESSAGE.msg() + ' Intent to authenticate needs to be expressed during initial connect request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.VERIFY_REQUEST, makeField(1) + makeField(apiName) + makeField(apiVersion))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_VERIFYREQUEST.code(), errors.FAIL_SEND_VERIFYREQUEST.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.verifyMessage = function (this: EClient, apiData: string): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support verification request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.VERIFY_MESSAGE, makeField(1) + makeField(apiData))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_VERIFYMESSAGE.code(), errors.FAIL_SEND_VERIFYMESSAGE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.verifyAndAuthRequest = function (
+ this: EClient, apiName: string, apiVersion: string, opaqueIsvKey: string,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support verification request.')
+ return
+ }
+
+ if (!this.extraAuth) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_VERIFYANDAUTHREQUEST.code(),
+ errors.FAIL_SEND_VERIFYANDAUTHREQUEST.msg() + ' Intent to authenticate needs to be expressed during initial connect request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.VERIFY_AND_AUTH_REQUEST, makeField(1) + makeField(apiName) + makeField(apiVersion) + makeField(opaqueIsvKey))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_VERIFYANDAUTHREQUEST.code(), errors.FAIL_SEND_VERIFYANDAUTHREQUEST.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.verifyAndAuthMessage = function (this: EClient, apiData: string, xyzResponse: string): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_LINKING) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support verification request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.VERIFY_AND_AUTH_MESSAGE, makeField(1) + makeField(apiData) + makeField(xyzResponse))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_VERIFYANDAUTHMESSAGE.code(), errors.FAIL_SEND_VERIFYANDAUTHMESSAGE.msg() + String(ex))
+ }
+ }
+
+ // ─── Security Definition Option Params ─────────────────────────────
+
+ Client.prototype.reqSecDefOptParams = function (
+ this: EClient, reqId: number, underlyingSymbol: string,
+ futFopExchange: string, underlyingSecType: string, underlyingConId: number,
+ ): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support security definition option request.')
+ return
+ }
+
+ try {
+ const flds = [
+ makeField(reqId),
+ makeField(underlyingSymbol),
+ makeField(futFopExchange),
+ makeField(underlyingSecType),
+ makeField(underlyingConId),
+ ]
+ this.sendMsg(OUT.REQ_SEC_DEF_OPT_PARAMS, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQSECDEFOPTPARAMS.code(), errors.FAIL_SEND_REQSECDEFOPTPARAMS.msg() + String(ex))
+ }
+ }
+
+ // ─── Soft Dollar Tiers ─────────────────────────────────────────────
+
+ Client.prototype.reqSoftDollarTiers = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_SOFT_DOLLAR_TIERS, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQSOFTDOLLARTIERS.code(), errors.FAIL_SEND_REQSOFTDOLLARTIERS.msg() + String(ex))
+ }
+ }
+
+ // ─── Family Codes ──────────────────────────────────────────────────
+
+ Client.prototype.reqFamilyCodes = function (this: EClient): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_FAMILY_CODES) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support family codes request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.REQ_FAMILY_CODES, '')
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQFAMILYCODES.code(), errors.FAIL_SEND_REQFAMILYCODES.msg() + String(ex))
+ }
+ }
+
+ // ─── Matching Symbols ──────────────────────────────────────────────
+
+ Client.prototype.reqMatchingSymbols = function (this: EClient, reqId: number, pattern: string): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_REQ_MATCHING_SYMBOLS) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support matching symbols request.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.REQ_MATCHING_SYMBOLS, makeField(reqId) + makeField(pattern))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQMATCHINGSYMBOLS.code(), errors.FAIL_SEND_REQMATCHINGSYMBOLS.msg() + String(ex))
+ }
+ }
+
+ // ─── WSH Meta Data / Event Data ────────────────────────────────────
+
+ Client.prototype.reqWshMetaData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_WSHE_CALENDAR) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support WSHE Calendar API.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.REQ_WSH_META_DATA, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQ_WSH_META_DATA.code(), errors.FAIL_SEND_REQ_WSH_META_DATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelWshMetaData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_WSHE_CALENDAR) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support WSHE Calendar API.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_WSH_META_DATA, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CAN_WSH_META_DATA.code(), errors.FAIL_SEND_CAN_WSH_META_DATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqWshEventData = function (this: EClient, reqId: number, wshEventData: WshEventData): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_WSHE_CALENDAR) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support WSHE Calendar API.')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS) {
+ if (wshEventData.filter !== '' || wshEventData.fillWatchlist || wshEventData.fillPortfolio || wshEventData.fillCompetitors) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support WSH event data filters.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE) {
+ if (wshEventData.startDate !== '' || wshEventData.endDate !== '' || wshEventData.totalLimit !== UNSET_INTEGER) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support WSH event data date filters.')
+ return
+ }
+ }
+
+ try {
+ const flds = [
+ makeField(reqId),
+ makeField(wshEventData.conId),
+ ]
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS) {
+ flds.push(
+ makeField(wshEventData.filter),
+ makeField(wshEventData.fillWatchlist),
+ makeField(wshEventData.fillPortfolio),
+ makeField(wshEventData.fillCompetitors),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE) {
+ flds.push(
+ makeField(wshEventData.startDate),
+ makeField(wshEventData.endDate),
+ makeField(wshEventData.totalLimit),
+ )
+ }
+
+ this.sendMsg(OUT.REQ_WSH_EVENT_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQ_WSH_EVENT_DATA.code(), errors.FAIL_SEND_REQ_WSH_EVENT_DATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelWshEventData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_WSHE_CALENDAR) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support WSHE Calendar API.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_WSH_EVENT_DATA, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CAN_WSH_EVENT_DATA.code(), errors.FAIL_SEND_CAN_WSH_EVENT_DATA.msg() + String(ex))
+ }
+ }
+
+ // ─── User Info ─────────────────────────────────────────────────────
+
+ Client.prototype.reqUserInfo = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_USER_INFO) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support user info requests.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.REQ_USER_INFO, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQ_USER_INFO.code(), errors.FAIL_SEND_REQ_USER_INFO.msg() + String(ex))
+ }
+ }
+
+ // ─── Cancel Contract Data ──────────────────────────────────────────
+
+ Client.prototype.cancelContractData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected(reqId)) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CANCEL_CONTRACT_DATA) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support contract data cancels.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_CONTRACT_DATA, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCEL_CONTRACT_DATA.code(), errors.FAIL_SEND_CANCEL_CONTRACT_DATA.msg() + String(ex))
+ }
+ }
+
+ // ─── Cancel Historical Ticks ───────────────────────────────────────
+
+ Client.prototype.cancelHistoricalTicks = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected(reqId)) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CANCEL_CONTRACT_DATA) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.UPDATE_TWS.code(),
+ errors.UPDATE_TWS.msg() + ' It does not support historical ticks cancels.')
+ return
+ }
+
+ try {
+ this.sendMsg(OUT.CANCEL_HISTORICAL_TICKS, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCEL_HISTORICAL_TICKS.code(), errors.FAIL_SEND_CANCEL_HISTORICAL_TICKS.msg() + String(ex))
+ }
+ }
+}
diff --git a/packages/ibkr/src/client/index.ts b/packages/ibkr/src/client/index.ts
new file mode 100644
index 00000000..ae5b9800
--- /dev/null
+++ b/packages/ibkr/src/client/index.ts
@@ -0,0 +1,22 @@
+/**
+ * EClient — assembled from base + method mixins.
+ *
+ * Usage:
+ * import { EClient } from '@traderalice/ibkr'
+ * const client = new EClient(myWrapper)
+ * await client.connect('127.0.0.1', 7497, 0)
+ */
+
+import { EClient } from './base.js'
+import { applyMarketData } from './market-data.js'
+import { applyAccount } from './account.js'
+import { applyOrders } from './orders.js'
+import { applyHistorical } from './historical.js'
+
+// Apply all method groups to EClient.prototype
+applyMarketData(EClient)
+applyAccount(EClient)
+applyOrders(EClient)
+applyHistorical(EClient)
+
+export { EClient }
diff --git a/packages/ibkr/src/client/market-data.ts b/packages/ibkr/src/client/market-data.ts
new file mode 100644
index 00000000..1cdd1a99
--- /dev/null
+++ b/packages/ibkr/src/client/market-data.ts
@@ -0,0 +1,283 @@
+/**
+ * EClient market data request methods.
+ * Mirrors: ibapi/client.py lines 627-1820
+ */
+
+import { EClient } from './base.js'
+import { encodeContractLegacy } from './encode.js'
+import { makeField, makeFieldHandleEmpty } from '../comm.js'
+import { OUT } from '../message.js'
+import * as SV from '../server-versions.js'
+import { NO_VALID_ID } from '../const.js'
+import * as errors from '../errors.js'
+import { currentTimeMillis } from '../utils.js'
+import type { Contract } from '../contract.js'
+import type { TagValueList } from '../tag-value.js'
+
+declare module './base.js' {
+ interface EClient {
+ reqCurrentTime(): void
+ reqCurrentTimeInMillis(): void
+ setServerLogLevel(logLevel: number): void
+ reqMktData(reqId: number, contract: Contract, genericTickList: string, snapshot: boolean, regulatorySnapshot: boolean, mktDataOptions: TagValueList): void
+ cancelMktData(reqId: number): void
+ reqMarketDataType(marketDataType: number): void
+ reqSmartComponents(reqId: number, bboExchange: string): void
+ reqMarketRule(marketRuleId: number): void
+ reqTickByTickData(reqId: number, contract: Contract, tickType: string, numberOfTicks: number, ignoreSize: boolean): void
+ cancelTickByTickData(reqId: number): void
+ calculateImpliedVolatility(reqId: number, contract: Contract, optionPrice: number, underPrice: number, implVolOptions: TagValueList): void
+ cancelCalculateImpliedVolatility(reqId: number): void
+ calculateOptionPrice(reqId: number, contract: Contract, volatility: number, underPrice: number, optPrcOptions: TagValueList): void
+ cancelCalculateOptionPrice(reqId: number): void
+ exerciseOptions(reqId: number, contract: Contract, exerciseAction: number, exerciseQuantity: number, account: string, override: number, manualOrderTime: string, customerAccount: string, professionalCustomer: boolean): void
+ }
+}
+
+export function applyMarketData(Client: typeof EClient): void {
+
+ Client.prototype.reqCurrentTime = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_CURRENT_TIME, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQCURRTIME.code(), errors.FAIL_SEND_REQCURRTIME.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqCurrentTimeInMillis = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_CURRENT_TIME_IN_MILLIS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQCURRTIMEINMILLIS.code(), errors.FAIL_SEND_REQCURRTIMEINMILLIS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.setServerLogLevel = function (this: EClient, logLevel: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.SET_SERVER_LOGLEVEL, makeField(1) + makeField(logLevel))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_SERVER_LOG_LEVEL.code(), errors.FAIL_SEND_SERVER_LOG_LEVEL.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqMktData = function (
+ this: EClient, reqId: number, contract: Contract, genericTickList: string,
+ snapshot: boolean, regulatorySnapshot: boolean, mktDataOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ const VERSION = 11
+ const flds: string[] = [makeField(VERSION), makeField(reqId)]
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_REQ_MKT_DATA_CONID) {
+ flds.push(makeField(contract.conId))
+ }
+
+ flds.push(
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ )
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.tradingClass))
+ }
+
+ // Combo legs for BAG
+ if (contract.secType === 'BAG') {
+ const comboLegsCount = contract.comboLegs?.length ?? 0
+ flds.push(makeField(comboLegsCount))
+ if (contract.comboLegs) {
+ for (const leg of contract.comboLegs) {
+ flds.push(makeField(leg.conId), makeField(leg.ratio), makeField(leg.action), makeField(leg.exchange))
+ }
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract) {
+ flds.push(makeField(true), makeField(contract.deltaNeutralContract.conId), makeField(contract.deltaNeutralContract.delta), makeField(contract.deltaNeutralContract.price))
+ } else {
+ flds.push(makeField(false))
+ }
+ }
+
+ flds.push(makeField(genericTickList), makeField(snapshot))
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_REQ_SMART_COMPONENTS) {
+ flds.push(makeField(regulatorySnapshot))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ flds.push(makeField('')) // mktDataOptions — internal use only
+ }
+
+ this.sendMsg(OUT.REQ_MKT_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQMKT.code(), errors.FAIL_SEND_REQMKT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelMktData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ this.sendMsg(OUT.CANCEL_MKT_DATA, makeField(2) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANMKT.code(), errors.FAIL_SEND_CANMKT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqMarketDataType = function (this: EClient, marketDataType: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_MARKET_DATA_TYPE, makeField(1) + makeField(marketDataType))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQMARKETDATATYPE.code(), errors.FAIL_SEND_REQMARKETDATATYPE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqSmartComponents = function (this: EClient, reqId: number, bboExchange: string): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_SMART_COMPONENTS, makeField(reqId) + makeField(bboExchange))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQSMARTCOMPONENTS.code(), errors.FAIL_SEND_REQSMARTCOMPONENTS.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqMarketRule = function (this: EClient, marketRuleId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_MARKET_RULE, makeField(marketRuleId))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQMARKETRULE.code(), errors.FAIL_SEND_REQMARKETRULE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqTickByTickData = function (
+ this: EClient, reqId: number, contract: Contract, tickType: string,
+ numberOfTicks: number, ignoreSize: boolean,
+ ): void {
+ if (!this.requireConnected()) return
+ try {
+ const flds = [
+ makeField(reqId),
+ ...encodeContractLegacy(this, contract),
+ makeField(tickType),
+ ]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE) {
+ flds.push(makeField(numberOfTicks), makeField(ignoreSize))
+ }
+ this.sendMsg(OUT.REQ_TICK_BY_TICK_DATA, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQTICKBYTICKDATA.code(), errors.FAIL_SEND_REQTICKBYTICKDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelTickByTickData = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.CANCEL_TICK_BY_TICK_DATA, makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCELTICKBYTICKDATA.code(), errors.FAIL_SEND_CANCELTICKBYTICKDATA.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.calculateImpliedVolatility = function (
+ this: EClient, reqId: number, contract: Contract,
+ optionPrice: number, underPrice: number, implVolOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ const flds = [
+ makeField(3), makeField(reqId),
+ makeField(contract.conId), makeField(contract.symbol), makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth), makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right), makeField(contract.multiplier), makeField(contract.exchange),
+ makeField(contract.primaryExchange), makeField(contract.currency), makeField(contract.localSymbol),
+ ]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.tradingClass))
+ flds.push(makeField(optionPrice), makeField(underPrice))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) flds.push(makeField(''))
+ this.sendMsg(OUT.REQ_CALC_IMPLIED_VOLAT, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQCALCIMPLIEDVOLAT.code(), errors.FAIL_SEND_REQCALCIMPLIEDVOLAT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelCalculateImpliedVolatility = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ this.sendMsg(OUT.CANCEL_CALC_IMPLIED_VOLAT, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCALCIMPLIEDVOLAT.code(), errors.FAIL_SEND_CANCALCIMPLIEDVOLAT.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.calculateOptionPrice = function (
+ this: EClient, reqId: number, contract: Contract,
+ volatility: number, underPrice: number, optPrcOptions: TagValueList,
+ ): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ const flds = [
+ makeField(3), makeField(reqId),
+ makeField(contract.conId), makeField(contract.symbol), makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth), makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right), makeField(contract.multiplier), makeField(contract.exchange),
+ makeField(contract.primaryExchange), makeField(contract.currency), makeField(contract.localSymbol),
+ ]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.tradingClass))
+ flds.push(makeField(volatility), makeField(underPrice))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) flds.push(makeField(''))
+ this.sendMsg(OUT.REQ_CALC_OPTION_PRICE, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQCALCOPTIONPRICE.code(), errors.FAIL_SEND_REQCALCOPTIONPRICE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelCalculateOptionPrice = function (this: EClient, reqId: number): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ this.sendMsg(OUT.CANCEL_CALC_OPTION_PRICE, makeField(1) + makeField(reqId))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_CANCALCOPTIONPRICE.code(), errors.FAIL_SEND_CANCALCOPTIONPRICE.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.exerciseOptions = function (
+ this: EClient, reqId: number, contract: Contract, exerciseAction: number,
+ exerciseQuantity: number, account: string, override: number,
+ manualOrderTime: string, customerAccount: string, professionalCustomer: boolean,
+ ): void {
+ if (!this.requireConnected(reqId)) return
+ try {
+ const flds = [makeField(2), makeField(reqId)]
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.conId))
+ flds.push(
+ makeField(contract.symbol), makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth), makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right), makeField(contract.multiplier), makeField(contract.exchange),
+ makeField(contract.currency), makeField(contract.localSymbol),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) flds.push(makeField(contract.tradingClass))
+ flds.push(makeField(exerciseAction), makeField(exerciseQuantity), makeField(account), makeField(override))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_MANUAL_ORDER_TIME_EXERCISE_OPTIONS) flds.push(makeField(manualOrderTime))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CUSTOMER_ACCOUNT) flds.push(makeField(customerAccount))
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PROFESSIONAL_CUSTOMER) flds.push(makeField(professionalCustomer))
+ this.sendMsg(OUT.EXERCISE_OPTIONS, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(reqId, currentTimeMillis(), errors.FAIL_SEND_REQMKT.code(), errors.FAIL_SEND_REQMKT.msg() + String(ex))
+ }
+ }
+}
diff --git a/packages/ibkr/src/client/orders.ts b/packages/ibkr/src/client/orders.ts
new file mode 100644
index 00000000..ac0e9578
--- /dev/null
+++ b/packages/ibkr/src/client/orders.ts
@@ -0,0 +1,888 @@
+/**
+ * EClient order methods — place, cancel, query orders.
+ * Mirrors: ibapi/client.py lines 1820-3210, 6984-7025
+ */
+
+import { EClient } from './base.js'
+import { makeField, makeFieldHandleEmpty } from '../comm.js'
+import { OUT } from '../message.js'
+import * as SV from '../server-versions.js'
+import { NO_VALID_ID, UNSET_DOUBLE, UNSET_INTEGER } from '../const.js'
+import * as errors from '../errors.js'
+import { currentTimeMillis, isPegBenchOrder, isPegBestOrder, isPegMidOrder } from '../utils.js'
+import { COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID } from '../order.js'
+import type { Contract } from '../contract.js'
+import type { Order } from '../order.js'
+import type { OrderCancel } from '../order-cancel.js'
+
+declare module './base.js' {
+ interface EClient {
+ placeOrder(orderId: number, contract: Contract, order: Order): void
+ cancelOrder(orderId: number, orderCancel: OrderCancel): void
+ reqOpenOrders(): void
+ reqAutoOpenOrders(bAutoBind: boolean): void
+ reqAllOpenOrders(): void
+ reqGlobalCancel(orderCancel: OrderCancel): void
+ reqIds(numIds: number): void
+ reqCompletedOrders(apiOnly: boolean): void
+ }
+}
+
+export function applyOrders(Client: typeof EClient): void {
+
+ Client.prototype.placeOrder = function (this: EClient, orderId: number, contract: Contract, order: Order): void {
+ if (!this.requireConnected(orderId)) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support delta-neutral orders.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SCALE_ORDERS2) {
+ if (order.scaleSubsLevelSize !== UNSET_INTEGER) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support Subsequent Level Size for Scale orders.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ALGO_ORDERS) {
+ if (order.algoStrategy) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support algo orders.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_NOT_HELD) {
+ if (order.notHeld) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support notHeld parameter.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SEC_ID_TYPE) {
+ if (contract.secIdType || contract.secId) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support secIdType and secId parameters.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_PLACE_ORDER_CONID) {
+ if (contract.conId && contract.conId > 0) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support conId parameter.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SSHORTX) {
+ if (order.exemptCode !== -1) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support exemptCode parameter.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SSHORTX) {
+ if (contract.comboLegs) {
+ for (const comboLeg of contract.comboLegs) {
+ if (comboLeg.exemptCode !== -1) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support exemptCode parameter.')
+ return
+ }
+ }
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_HEDGE_ORDERS) {
+ if (order.hedgeType) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support hedge orders.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) {
+ if (order.optOutSmartRouting) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support optOutSmartRouting parameter.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_DELTA_NEUTRAL_CONID) {
+ if (
+ order.deltaNeutralConId > 0 ||
+ order.deltaNeutralSettlingFirm ||
+ order.deltaNeutralClearingAccount ||
+ order.deltaNeutralClearingIntent
+ ) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support deltaNeutral parameters: ConId, SettlingFirm, ClearingAccount, ClearingIntent.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE) {
+ if (
+ order.deltaNeutralOpenClose ||
+ order.deltaNeutralShortSale ||
+ order.deltaNeutralShortSaleSlot > 0 ||
+ order.deltaNeutralDesignatedLocation
+ ) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support deltaNeutral parameters: OpenClose, ShortSale, ShortSaleSlot, DesignatedLocation.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SCALE_ORDERS3) {
+ if (order.scalePriceIncrement > 0 && order.scalePriceIncrement !== UNSET_DOUBLE) {
+ if (
+ order.scalePriceAdjustValue !== UNSET_DOUBLE ||
+ order.scalePriceAdjustInterval !== UNSET_INTEGER ||
+ order.scaleProfitOffset !== UNSET_DOUBLE ||
+ order.scaleAutoReset ||
+ order.scaleInitPosition !== UNSET_INTEGER ||
+ order.scaleInitFillQty !== UNSET_INTEGER ||
+ order.scaleRandomPercent
+ ) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support Scale order parameters: PriceAdjustValue, PriceAdjustInterval, ProfitOffset, AutoReset, InitPosition, InitFillQty and RandomPercent')
+ return
+ }
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && contract.secType === 'BAG') {
+ if (order.orderComboLegs) {
+ for (const orderComboLeg of order.orderComboLegs) {
+ if (orderComboLeg.price !== UNSET_DOUBLE) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support per-leg prices for order combo legs.')
+ return
+ }
+ }
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_TRAILING_PERCENT) {
+ if (order.trailingPercent !== UNSET_DOUBLE) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support trailing percent parameter')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_TRADING_CLASS) {
+ if (contract.tradingClass) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support tradingClass parameter in placeOrder.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SCALE_TABLE) {
+ if (order.scaleTable || order.activeStartTime || order.activeStopTime) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support scaleTable, activeStartTime and activeStopTime parameters')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ALGO_ID) {
+ if (order.algoId) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support algoId parameter')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ORDER_SOLICITED) {
+ if (order.solicited) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support order solicited parameter.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_MODELS_SUPPORT) {
+ if (order.modelCode) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support model code parameter.')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_EXT_OPERATOR) {
+ if (order.extOperator) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support ext operator parameter')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_SOFT_DOLLAR_TIER) {
+ if (order.softDollarTier.name || order.softDollarTier.val) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support soft dollar tier')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CASH_QTY) {
+ if (order.cashQty) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support cash quantity parameter')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_DECISION_MAKER && (order.mifid2DecisionMaker !== '' || order.mifid2DecisionAlgo !== '')) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support MIFID II decision maker parameters')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_MIFID_EXECUTION && (order.mifid2ExecutionTrader !== '' || order.mifid2ExecutionAlgo !== '')) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support MIFID II execution parameters')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE && order.dontUseAutoPriceForHedge) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support dontUseAutoPriceForHedge parameter')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ORDER_CONTAINER && order.isOmsContainer) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support oms container parameter')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_PRICE_MGMT_ALGO && order.usePriceMgmtAlgo) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support Use price management algo requests')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_DURATION && order.duration !== UNSET_INTEGER) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support duration attribute')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_POST_TO_ATS && order.postToAts !== UNSET_INTEGER) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support postToAts attribute')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_AUTO_CANCEL_PARENT && order.autoCancelParent) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support autoCancelParent attribute')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ADVANCED_ORDER_REJECT && order.advancedErrorOverride) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support advanced error override attribute')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_MANUAL_ORDER_TIME && order.manualOrderTime) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support manual order time attribute')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS) {
+ if (
+ order.minTradeQty !== UNSET_INTEGER ||
+ order.minCompeteSize !== UNSET_INTEGER ||
+ order.competeAgainstBestOffset !== UNSET_DOUBLE ||
+ order.midOffsetAtWhole !== UNSET_DOUBLE ||
+ order.midOffsetAtHalf !== UNSET_DOUBLE
+ ) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support PEG BEST / PEG MID order parameters: minTradeQty, minCompeteSize, competeAgainstBestOffset, midOffsetAtWhole and midOffsetAtHalf')
+ return
+ }
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CUSTOMER_ACCOUNT && order.customerAccount) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support customer account parameter')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_PROFESSIONAL_CUSTOMER && order.professionalCustomer) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support professional customer parameter')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_INCLUDE_OVERNIGHT && order.includeOvernight) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support include overnight parameter')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CME_TAGGING_FIELDS && order.manualOrderIndicator !== UNSET_INTEGER) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support manual order indicator parameters')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_IMBALANCE_ONLY && order.imbalanceOnly) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support imbalance only parameter')
+ return
+ }
+
+ try {
+ const VERSION = this.serverVersion() < SV.MIN_SERVER_VER_NOT_HELD ? 27 : 45
+
+ const flds: string[] = []
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ORDER_CONTAINER) {
+ flds.push(makeField(VERSION))
+ }
+
+ flds.push(makeField(orderId))
+
+ // send contract fields
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PLACE_ORDER_CONID) {
+ flds.push(makeField(contract.conId))
+ }
+ flds.push(
+ makeField(contract.symbol),
+ makeField(contract.secType),
+ makeField(contract.lastTradeDateOrContractMonth),
+ makeFieldHandleEmpty(contract.strike),
+ makeField(contract.right),
+ makeField(contract.multiplier),
+ makeField(contract.exchange),
+ makeField(contract.primaryExchange),
+ makeField(contract.currency),
+ makeField(contract.localSymbol),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRADING_CLASS) {
+ flds.push(makeField(contract.tradingClass))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SEC_ID_TYPE) {
+ flds.push(makeField(contract.secIdType), makeField(contract.secId))
+ }
+
+ // send main order fields
+ flds.push(makeField(order.action))
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_FRACTIONAL_POSITIONS) {
+ flds.push(makeField(order.totalQuantity))
+ } else {
+ flds.push(makeField(order.totalQuantity.toNumber() | 0))
+ }
+
+ flds.push(makeField(order.orderType))
+ if (this.serverVersion() < SV.MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE) {
+ flds.push(makeField(order.lmtPrice !== UNSET_DOUBLE ? order.lmtPrice : 0))
+ } else {
+ flds.push(makeFieldHandleEmpty(order.lmtPrice))
+ }
+ if (this.serverVersion() < SV.MIN_SERVER_VER_TRAILING_PERCENT) {
+ flds.push(makeField(order.auxPrice !== UNSET_DOUBLE ? order.auxPrice : 0))
+ } else {
+ flds.push(makeFieldHandleEmpty(order.auxPrice))
+ }
+
+ // send extended order fields
+ flds.push(
+ makeField(order.tif),
+ makeField(order.ocaGroup),
+ makeField(order.account),
+ makeField(order.openClose),
+ makeField(order.origin),
+ makeField(order.orderRef),
+ makeField(order.transmit),
+ makeField(order.parentId),
+ makeField(order.blockOrder),
+ makeField(order.sweepToFill),
+ makeField(order.displaySize),
+ makeField(order.triggerMethod),
+ makeField(order.outsideRth),
+ makeField(order.hidden),
+ )
+
+ // Send combo legs for BAG requests
+ if (contract.secType === 'BAG') {
+ const comboLegsCount = contract.comboLegs?.length ?? 0
+ flds.push(makeField(comboLegsCount))
+ if (comboLegsCount > 0 && contract.comboLegs) {
+ for (const comboLeg of contract.comboLegs) {
+ flds.push(
+ makeField(comboLeg.conId),
+ makeField(comboLeg.ratio),
+ makeField(comboLeg.action),
+ makeField(comboLeg.exchange),
+ makeField(comboLeg.openClose),
+ makeField(comboLeg.shortSaleSlot),
+ makeField(comboLeg.designatedLocation),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SSHORTX_OLD) {
+ flds.push(makeField(comboLeg.exemptCode))
+ }
+ }
+ }
+ }
+
+ // Send order combo legs for BAG requests
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE && contract.secType === 'BAG') {
+ const orderComboLegsCount = order.orderComboLegs?.length ?? 0
+ flds.push(makeField(orderComboLegsCount))
+ if (orderComboLegsCount > 0 && order.orderComboLegs) {
+ for (const orderComboLeg of order.orderComboLegs) {
+ flds.push(makeFieldHandleEmpty(orderComboLeg.price))
+ }
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS && contract.secType === 'BAG') {
+ const smartComboRoutingParamsCount = order.smartComboRoutingParams?.length ?? 0
+ flds.push(makeField(smartComboRoutingParamsCount))
+ if (smartComboRoutingParamsCount > 0 && order.smartComboRoutingParams) {
+ for (const tagValue of order.smartComboRoutingParams) {
+ flds.push(makeField(tagValue.tag), makeField(tagValue.value))
+ }
+ }
+ }
+
+ // send deprecated sharesAllocation field
+ flds.push(
+ makeField(''),
+ makeField(order.discretionaryAmt),
+ makeField(order.goodAfterTime),
+ makeField(order.goodTillDate),
+ makeField(order.faGroup),
+ makeField(order.faMethod),
+ makeField(order.faPercentage),
+ )
+ if (this.serverVersion() < SV.MIN_SERVER_VER_FA_PROFILE_DESUPPORT) {
+ flds.push(makeField('')) // send deprecated faProfile field
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_MODELS_SUPPORT) {
+ flds.push(makeField(order.modelCode))
+ }
+
+ // institutional short sale slot data
+ flds.push(
+ makeField(order.shortSaleSlot),
+ makeField(order.designatedLocation),
+ )
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SSHORTX_OLD) {
+ flds.push(makeField(order.exemptCode))
+ }
+
+ flds.push(makeField(order.ocaType))
+
+ flds.push(
+ makeField(order.rule80A),
+ makeField(order.settlingFirm),
+ makeField(order.allOrNone),
+ makeFieldHandleEmpty(order.minQty),
+ makeFieldHandleEmpty(order.percentOffset),
+ makeField(false),
+ makeField(false),
+ makeFieldHandleEmpty(UNSET_DOUBLE),
+ makeField(order.auctionStrategy),
+ makeFieldHandleEmpty(order.startingPrice),
+ makeFieldHandleEmpty(order.stockRefPrice),
+ makeFieldHandleEmpty(order.delta),
+ makeFieldHandleEmpty(order.stockRangeLower),
+ makeFieldHandleEmpty(order.stockRangeUpper),
+ makeField(order.overridePercentageConstraints),
+ // Volatility orders
+ makeFieldHandleEmpty(order.volatility),
+ makeFieldHandleEmpty(order.volatilityType),
+ makeField(order.deltaNeutralOrderType),
+ makeFieldHandleEmpty(order.deltaNeutralAuxPrice),
+ )
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_DELTA_NEUTRAL_CONID && order.deltaNeutralOrderType) {
+ flds.push(
+ makeField(order.deltaNeutralConId),
+ makeField(order.deltaNeutralSettlingFirm),
+ makeField(order.deltaNeutralClearingAccount),
+ makeField(order.deltaNeutralClearingIntent),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE && order.deltaNeutralOrderType) {
+ flds.push(
+ makeField(order.deltaNeutralOpenClose),
+ makeField(order.deltaNeutralShortSale),
+ makeField(order.deltaNeutralShortSaleSlot),
+ makeField(order.deltaNeutralDesignatedLocation),
+ )
+ }
+
+ flds.push(
+ makeField(order.continuousUpdate),
+ makeFieldHandleEmpty(order.referencePriceType),
+ makeFieldHandleEmpty(order.trailStopPrice),
+ )
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_TRAILING_PERCENT) {
+ flds.push(makeFieldHandleEmpty(order.trailingPercent))
+ }
+
+ // SCALE orders
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SCALE_ORDERS2) {
+ flds.push(
+ makeFieldHandleEmpty(order.scaleInitLevelSize),
+ makeFieldHandleEmpty(order.scaleSubsLevelSize),
+ )
+ } else {
+ flds.push(
+ makeField(''), // for not supported scaleNumComponents
+ makeFieldHandleEmpty(order.scaleInitLevelSize),
+ )
+ }
+
+ flds.push(makeFieldHandleEmpty(order.scalePriceIncrement))
+
+ if (
+ this.serverVersion() >= SV.MIN_SERVER_VER_SCALE_ORDERS3 &&
+ order.scalePriceIncrement !== UNSET_DOUBLE &&
+ order.scalePriceIncrement > 0.0
+ ) {
+ flds.push(
+ makeFieldHandleEmpty(order.scalePriceAdjustValue),
+ makeFieldHandleEmpty(order.scalePriceAdjustInterval),
+ makeFieldHandleEmpty(order.scaleProfitOffset),
+ makeField(order.scaleAutoReset),
+ makeFieldHandleEmpty(order.scaleInitPosition),
+ makeFieldHandleEmpty(order.scaleInitFillQty),
+ makeField(order.scaleRandomPercent),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SCALE_TABLE) {
+ flds.push(
+ makeField(order.scaleTable),
+ makeField(order.activeStartTime),
+ makeField(order.activeStopTime),
+ )
+ }
+
+ // HEDGE orders
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_HEDGE_ORDERS) {
+ flds.push(makeField(order.hedgeType))
+ if (order.hedgeType) {
+ flds.push(makeField(order.hedgeParam))
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_OPT_OUT_SMART_ROUTING) {
+ flds.push(makeField(order.optOutSmartRouting))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PTA_ORDERS) {
+ flds.push(
+ makeField(order.clearingAccount),
+ makeField(order.clearingIntent),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_NOT_HELD) {
+ flds.push(makeField(order.notHeld))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_DELTA_NEUTRAL) {
+ if (contract.deltaNeutralContract) {
+ flds.push(
+ makeField(true),
+ makeField(contract.deltaNeutralContract.conId),
+ makeField(contract.deltaNeutralContract.delta),
+ makeField(contract.deltaNeutralContract.price),
+ )
+ } else {
+ flds.push(makeField(false))
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_ALGO_ORDERS) {
+ flds.push(makeField(order.algoStrategy))
+ if (order.algoStrategy) {
+ const algoParamsCount = order.algoParams?.length ?? 0
+ flds.push(makeField(algoParamsCount))
+ if (algoParamsCount > 0 && order.algoParams) {
+ for (const algoParam of order.algoParams) {
+ flds.push(makeField(algoParam.tag), makeField(algoParam.value))
+ }
+ }
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_ALGO_ID) {
+ flds.push(makeField(order.algoId))
+ }
+
+ flds.push(makeField(order.whatIf))
+
+ // send miscOptions parameter
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_LINKING) {
+ let miscOptionsStr = ''
+ if (order.orderMiscOptions) {
+ for (const tagValue of order.orderMiscOptions) {
+ miscOptionsStr += String(tagValue)
+ }
+ }
+ flds.push(makeField(miscOptionsStr))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_ORDER_SOLICITED) {
+ flds.push(makeField(order.solicited))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE) {
+ flds.push(
+ makeField(order.randomizeSize),
+ makeField(order.randomizePrice),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PEGGED_TO_BENCHMARK) {
+ if (isPegBenchOrder(order.orderType)) {
+ flds.push(
+ makeField(order.referenceContractId),
+ makeField(order.isPeggedChangeAmountDecrease),
+ makeField(order.peggedChangeAmount),
+ makeField(order.referenceChangeAmount),
+ makeField(order.referenceExchangeId),
+ )
+ }
+
+ flds.push(makeField(order.conditions.length))
+
+ if (order.conditions.length > 0) {
+ for (const cond of order.conditions) {
+ flds.push(makeField(cond.type()))
+ flds.push(...cond.makeFields())
+ }
+
+ flds.push(
+ makeField(order.conditionsIgnoreRth),
+ makeField(order.conditionsCancelOrder),
+ )
+ }
+
+ flds.push(
+ makeField(order.adjustedOrderType),
+ makeField(order.triggerPrice),
+ makeField(order.lmtPriceOffset),
+ makeField(order.adjustedStopPrice),
+ makeField(order.adjustedStopLimitPrice),
+ makeField(order.adjustedTrailingAmount),
+ makeField(order.adjustableTrailingUnit),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_EXT_OPERATOR) {
+ flds.push(makeField(order.extOperator))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_SOFT_DOLLAR_TIER) {
+ flds.push(
+ makeField(order.softDollarTier.name),
+ makeField(order.softDollarTier.val),
+ )
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CASH_QTY) {
+ flds.push(makeField(order.cashQty))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_DECISION_MAKER) {
+ flds.push(makeField(order.mifid2DecisionMaker))
+ flds.push(makeField(order.mifid2DecisionAlgo))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_MIFID_EXECUTION) {
+ flds.push(makeField(order.mifid2ExecutionTrader))
+ flds.push(makeField(order.mifid2ExecutionAlgo))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE) {
+ flds.push(makeField(order.dontUseAutoPriceForHedge))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_ORDER_CONTAINER) {
+ flds.push(makeField(order.isOmsContainer))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_D_PEG_ORDERS) {
+ flds.push(makeField(order.discretionaryUpToLimitPrice))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PRICE_MGMT_ALGO) {
+ flds.push(makeFieldHandleEmpty(
+ order.usePriceMgmtAlgo == null
+ ? UNSET_INTEGER
+ : order.usePriceMgmtAlgo ? 1 : 0
+ ))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_DURATION) {
+ flds.push(makeField(order.duration))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_POST_TO_ATS) {
+ flds.push(makeField(order.postToAts))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_AUTO_CANCEL_PARENT) {
+ flds.push(makeField(order.autoCancelParent))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_ADVANCED_ORDER_REJECT) {
+ flds.push(makeField(order.advancedErrorOverride))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_MANUAL_ORDER_TIME) {
+ flds.push(makeField(order.manualOrderTime))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS) {
+ let sendMidOffsets = false
+ if (contract.exchange === 'IBKRATS') {
+ flds.push(makeFieldHandleEmpty(order.minTradeQty))
+ }
+ if (isPegBestOrder(order.orderType)) {
+ flds.push(makeFieldHandleEmpty(order.minCompeteSize))
+ flds.push(makeFieldHandleEmpty(order.competeAgainstBestOffset))
+ if (order.competeAgainstBestOffset === COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID) {
+ sendMidOffsets = true
+ }
+ } else if (isPegMidOrder(order.orderType)) {
+ sendMidOffsets = true
+ }
+ if (sendMidOffsets) {
+ flds.push(makeFieldHandleEmpty(order.midOffsetAtWhole))
+ flds.push(makeFieldHandleEmpty(order.midOffsetAtHalf))
+ }
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CUSTOMER_ACCOUNT) {
+ flds.push(makeField(order.customerAccount))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_PROFESSIONAL_CUSTOMER) {
+ flds.push(makeField(order.professionalCustomer))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_RFQ_FIELDS && this.serverVersion() < SV.MIN_SERVER_VER_UNDO_RFQ_FIELDS) {
+ flds.push(makeField(''))
+ flds.push(makeField(UNSET_INTEGER))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_INCLUDE_OVERNIGHT) {
+ flds.push(makeField(order.includeOvernight))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CME_TAGGING_FIELDS) {
+ flds.push(makeField(order.manualOrderIndicator))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_IMBALANCE_ONLY) {
+ flds.push(makeField(order.imbalanceOnly))
+ }
+
+ this.sendMsg(OUT.PLACE_ORDER, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.FAIL_SEND_ORDER.code(), errors.FAIL_SEND_ORDER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.cancelOrder = function (this: EClient, orderId: number, orderCancel: OrderCancel): void {
+ if (!this.requireConnected(orderId)) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_MANUAL_ORDER_TIME && orderCancel.manualOrderCancelTime) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support manual order cancel time attribute')
+ return
+ }
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CME_TAGGING_FIELDS && (orderCancel.extOperator !== '' || orderCancel.manualOrderIndicator !== UNSET_INTEGER)) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support ext operator and manual order indicator parameters')
+ return
+ }
+
+ try {
+ const flds: string[] = []
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CME_TAGGING_FIELDS) {
+ flds.push(makeField(1)) // VERSION
+ }
+ flds.push(makeField(orderId))
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_MANUAL_ORDER_TIME) {
+ flds.push(makeField(orderCancel.manualOrderCancelTime))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_RFQ_FIELDS && this.serverVersion() < SV.MIN_SERVER_VER_UNDO_RFQ_FIELDS) {
+ flds.push(makeField(''))
+ flds.push(makeField(''))
+ flds.push(makeField(UNSET_INTEGER))
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CME_TAGGING_FIELDS) {
+ flds.push(makeField(orderCancel.extOperator))
+ flds.push(makeField(orderCancel.manualOrderIndicator))
+ }
+
+ this.sendMsg(OUT.CANCEL_ORDER, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(orderId, currentTimeMillis(), errors.FAIL_SEND_CORDER.code(), errors.FAIL_SEND_CORDER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqOpenOrders = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_OPEN_ORDERS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_OORDER.code(), errors.FAIL_SEND_OORDER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqAutoOpenOrders = function (this: EClient, bAutoBind: boolean): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_AUTO_OPEN_ORDERS, makeField(1) + makeField(bAutoBind))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_OORDER.code(), errors.FAIL_SEND_OORDER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqAllOpenOrders = function (this: EClient): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_ALL_OPEN_ORDERS, makeField(1))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_OORDER.code(), errors.FAIL_SEND_OORDER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqGlobalCancel = function (this: EClient, orderCancel: OrderCancel): void {
+ if (!this.requireConnected()) return
+
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CME_TAGGING_FIELDS && (orderCancel.extOperator !== '' || orderCancel.manualOrderIndicator !== UNSET_INTEGER)) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.UPDATE_TWS.code(), errors.UPDATE_TWS.msg() + ' It does not support ext operator and manual order indicator parameters')
+ return
+ }
+
+ try {
+ const flds: string[] = []
+ if (this.serverVersion() < SV.MIN_SERVER_VER_CME_TAGGING_FIELDS) {
+ flds.push(makeField(1)) // VERSION
+ }
+
+ if (this.serverVersion() >= SV.MIN_SERVER_VER_CME_TAGGING_FIELDS) {
+ flds.push(makeField(orderCancel.extOperator))
+ flds.push(makeField(orderCancel.manualOrderIndicator))
+ }
+
+ this.sendMsg(OUT.REQ_GLOBAL_CANCEL, flds.join(''))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQGLOBALCANCEL.code(), errors.FAIL_SEND_REQGLOBALCANCEL.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqIds = function (this: EClient, numIds: number): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_IDS, makeField(1) + makeField(numIds))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_CORDER.code(), errors.FAIL_SEND_CORDER.msg() + String(ex))
+ }
+ }
+
+ Client.prototype.reqCompletedOrders = function (this: EClient, apiOnly: boolean): void {
+ if (!this.requireConnected()) return
+ try {
+ this.sendMsg(OUT.REQ_COMPLETED_ORDERS, makeField(apiOnly))
+ } catch (ex: any) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), errors.FAIL_SEND_REQCOMPLETEDORDERS.code(), errors.FAIL_SEND_REQCOMPLETEDORDERS.msg() + String(ex))
+ }
+ }
+}
diff --git a/packages/ibkr/src/comm.ts b/packages/ibkr/src/comm.ts
new file mode 100644
index 00000000..9fde2c4c
--- /dev/null
+++ b/packages/ibkr/src/comm.ts
@@ -0,0 +1,121 @@
+/**
+ * Low-level IB message framing — encode/decode with length prefix.
+ * Mirrors: ibapi/comm.py
+ */
+
+import { UNSET_INTEGER, UNSET_DOUBLE, DOUBLE_INFINITY, INFINITY_STR } from './const.js'
+import { ClientException, isAsciiPrintable } from './utils.js'
+import { INVALID_SYMBOL } from './errors.js'
+
+/**
+ * Wrap protobuf data with 4-byte big-endian length prefix and msgId.
+ * Wire format: [4-byte total length][4-byte msgId BE][protobuf bytes]
+ */
+export function makeMsgProto(msgId: number, protobufData: Buffer): Buffer {
+ const msgIdBuf = Buffer.alloc(4)
+ msgIdBuf.writeUInt32BE(msgId)
+ const payload = Buffer.concat([msgIdBuf, protobufData])
+ const header = Buffer.alloc(4)
+ header.writeUInt32BE(payload.length)
+ return Buffer.concat([header, payload])
+}
+
+/**
+ * Wrap text message with 4-byte length prefix.
+ * If useRawIntMsgId, msgId is sent as 4-byte BE int before text.
+ * Otherwise msgId is sent as a NULL-terminated text field.
+ */
+export function makeMsg(msgId: number, useRawIntMsgId: boolean, text: string): Buffer {
+ let payload: Buffer
+ if (useRawIntMsgId) {
+ const msgIdBuf = Buffer.alloc(4)
+ msgIdBuf.writeUInt32BE(msgId)
+ payload = Buffer.concat([msgIdBuf, Buffer.from(text, 'utf-8')])
+ } else {
+ payload = Buffer.from(makeField(msgId) + text, 'utf-8')
+ }
+ const header = Buffer.alloc(4)
+ header.writeUInt32BE(payload.length)
+ return Buffer.concat([header, payload])
+}
+
+/**
+ * Wrap initial handshake text with length prefix.
+ */
+export function makeInitialMsg(text: string): Buffer {
+ const payload = Buffer.from(text, 'utf-8')
+ const header = Buffer.alloc(4)
+ header.writeUInt32BE(payload.length)
+ return Buffer.concat([header, payload])
+}
+
+/**
+ * Encode a value as a NULL-terminated string field.
+ */
+export function makeField(val: unknown): string {
+ if (val === null || val === undefined) {
+ throw new Error('Cannot send None to TWS')
+ }
+
+ // Validate printable ASCII for strings
+ if (typeof val === 'string' && val.length > 0 && !isAsciiPrintable(val)) {
+ throw new ClientException(
+ INVALID_SYMBOL.code(),
+ INVALID_SYMBOL.msg(),
+ val,
+ )
+ }
+
+ // bool → int
+ if (typeof val === 'boolean') {
+ return (val ? 1 : 0) + '\0'
+ }
+
+ return String(val) + '\0'
+}
+
+/**
+ * Like makeField but handles UNSET/INFINITY sentinel values.
+ */
+export function makeFieldHandleEmpty(val: unknown): string {
+ if (val === null || val === undefined) {
+ throw new Error('Cannot send None to TWS')
+ }
+
+ if (val === UNSET_INTEGER || val === UNSET_DOUBLE) {
+ return makeField('')
+ }
+
+ if (val === DOUBLE_INFINITY) {
+ return makeField(INFINITY_STR)
+ }
+
+ return makeField(val)
+}
+
+/**
+ * Read a length-prefixed message from a buffer.
+ * Returns [size, msg, remainingBuf].
+ * If incomplete, msg is empty Buffer.
+ */
+export function readMsg(buf: Buffer): [number, Buffer, Buffer] {
+ if (buf.length < 4) {
+ return [0, Buffer.alloc(0), buf]
+ }
+ const size = buf.readUInt32BE(0)
+ if (buf.length - 4 >= size) {
+ const msg = buf.subarray(4, 4 + size)
+ const rest = buf.subarray(4 + size)
+ return [size, msg, rest]
+ }
+ return [size, Buffer.alloc(0), buf]
+}
+
+/**
+ * Split a message payload into NULL-separated fields.
+ */
+export function readFields(buf: Buffer): string[] {
+ const parts = buf.toString('utf-8').split('\0')
+ // Last element is empty (trailing NULL)
+ return parts.slice(0, -1)
+}
diff --git a/packages/ibkr/src/commission-and-fees-report.ts b/packages/ibkr/src/commission-and-fees-report.ts
new file mode 100644
index 00000000..051c3319
--- /dev/null
+++ b/packages/ibkr/src/commission-and-fees-report.ts
@@ -0,0 +1,29 @@
+/**
+ * Mirrors: ibapi/commission_and_fees_report.py
+ */
+
+function floatMaxString(val: number): string {
+ return val === Number.MAX_VALUE ? '' : String(val)
+}
+
+function intMaxString(val: number): string {
+ return val === 2 ** 31 - 1 ? '' : String(val)
+}
+
+export class CommissionAndFeesReport {
+ execId = ''
+ commissionAndFees = 0.0
+ currency = ''
+ realizedPNL = 0.0
+ yield_ = 0.0
+ yieldRedemptionDate = 0 // YYYYMMDD format
+
+ toString(): string {
+ return (
+ `ExecId: ${this.execId}, CommissionAndFees: ${floatMaxString(this.commissionAndFees)}, ` +
+ `Currency: ${this.currency}, RealizedPnL: ${floatMaxString(this.realizedPNL)}, ` +
+ `Yield: ${floatMaxString(this.yield_)}, ` +
+ `YieldRedemptionDate: ${intMaxString(this.yieldRedemptionDate)}`
+ )
+ }
+}
diff --git a/packages/ibkr/src/common.ts b/packages/ibkr/src/common.ts
new file mode 100644
index 00000000..2e8a8724
--- /dev/null
+++ b/packages/ibkr/src/common.ts
@@ -0,0 +1,406 @@
+/**
+ * Mirrors: ibapi/common.py
+ */
+
+import Decimal from 'decimal.js'
+import { UNSET_INTEGER, UNSET_DECIMAL } from './const.js'
+import { OUT } from './message.js'
+import {
+ MIN_SERVER_VER_PROTOBUF,
+ MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ MIN_SERVER_VER_PROTOBUF_CONTRACT_DATA,
+ MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+} from './server-versions.js'
+
+function floatMaxString(val: number): string {
+ return val === Number.MAX_VALUE ? '' : String(val)
+}
+
+function decimalMaxString(val: Decimal): string {
+ return val.eq(UNSET_DECIMAL) ? '' : val.toString()
+}
+
+function intMaxString(val: number): string {
+ return val === UNSET_INTEGER ? '' : String(val)
+}
+
+// --- Type aliases ---
+
+export type TickerId = number
+export type OrderId = number
+export type TagValueList = Array<{ tag: string; value: string }>
+
+export type FaDataType = number
+export const FaDataTypeEnum = {
+ 'N/A': 0,
+ GROUPS: 1,
+ 'N/A2': 2,
+ ALIASES: 3,
+} as const
+
+export type MarketDataType = number
+export const MarketDataTypeEnum = {
+ 'N/A': 0,
+ REALTIME: 1,
+ FROZEN: 2,
+ DELAYED: 3,
+ DELAYED_FROZEN: 4,
+} as const
+
+export type Liquidities = number
+export const LiquiditiesEnum = {
+ None: 0,
+ Added: 1,
+ Remove: 2,
+ RoudedOut: 3,
+} as const
+
+export type SetOfString = Set
+export type SetOfFloat = Set
+export type ListOfOrder = unknown[]
+export type ListOfFamilyCode = FamilyCode[]
+export type ListOfContractDescription = unknown[]
+export type ListOfDepthExchanges = DepthMktDataDescription[]
+export type ListOfNewsProviders = NewsProvider[]
+export type SmartComponentMap = Map
+export type HistogramDataList = HistogramData[]
+export type ListOfPriceIncrements = PriceIncrement[]
+export type ListOfHistoricalTick = HistoricalTick[]
+export type ListOfHistoricalTickBidAsk = HistoricalTickBidAsk[]
+export type ListOfHistoricalTickLast = HistoricalTickLast[]
+export type ListOfHistoricalSessions = HistoricalSession[]
+
+// --- Protobuf message ID map ---
+
+export const PROTOBUF_MSG_ID = 200
+
+export const PROTOBUF_MSG_IDS: Record = {
+ [OUT.REQ_EXECUTIONS]: MIN_SERVER_VER_PROTOBUF,
+ [OUT.PLACE_ORDER]: MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ [OUT.CANCEL_ORDER]: MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ [OUT.REQ_GLOBAL_CANCEL]: MIN_SERVER_VER_PROTOBUF_PLACE_ORDER,
+ [OUT.REQ_ALL_OPEN_ORDERS]: MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ [OUT.REQ_AUTO_OPEN_ORDERS]: MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ [OUT.REQ_OPEN_ORDERS]: MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ [OUT.REQ_COMPLETED_ORDERS]: MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER,
+ [OUT.REQ_CONTRACT_DATA]: MIN_SERVER_VER_PROTOBUF_CONTRACT_DATA,
+ [OUT.REQ_MKT_DATA]: MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ [OUT.CANCEL_MKT_DATA]: MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ [OUT.REQ_MKT_DEPTH]: MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ [OUT.CANCEL_MKT_DEPTH]: MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ [OUT.REQ_MARKET_DATA_TYPE]: MIN_SERVER_VER_PROTOBUF_MARKET_DATA,
+ [OUT.REQ_ACCT_DATA]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.REQ_MANAGED_ACCTS]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.REQ_POSITIONS]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.CANCEL_POSITIONS]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.REQ_ACCOUNT_SUMMARY]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.CANCEL_ACCOUNT_SUMMARY]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.REQ_POSITIONS_MULTI]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.CANCEL_POSITIONS_MULTI]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.REQ_ACCOUNT_UPDATES_MULTI]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.CANCEL_ACCOUNT_UPDATES_MULTI]: MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS,
+ [OUT.REQ_HISTORICAL_DATA]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.CANCEL_HISTORICAL_DATA]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.REQ_REAL_TIME_BARS]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.CANCEL_REAL_TIME_BARS]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.REQ_HEAD_TIMESTAMP]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.CANCEL_HEAD_TIMESTAMP]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.REQ_HISTOGRAM_DATA]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.CANCEL_HISTOGRAM_DATA]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.REQ_HISTORICAL_TICKS]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.REQ_TICK_BY_TICK_DATA]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.CANCEL_TICK_BY_TICK_DATA]: MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA,
+ [OUT.REQ_NEWS_BULLETINS]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.CANCEL_NEWS_BULLETINS]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.REQ_NEWS_ARTICLE]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.REQ_NEWS_PROVIDERS]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.REQ_HISTORICAL_NEWS]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.REQ_WSH_META_DATA]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.CANCEL_WSH_META_DATA]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.REQ_WSH_EVENT_DATA]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.CANCEL_WSH_EVENT_DATA]: MIN_SERVER_VER_PROTOBUF_NEWS_DATA,
+ [OUT.REQ_SCANNER_PARAMETERS]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.REQ_SCANNER_SUBSCRIPTION]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.CANCEL_SCANNER_SUBSCRIPTION]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.REQ_FUNDAMENTAL_DATA]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.CANCEL_FUNDAMENTAL_DATA]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.REQ_PNL]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.CANCEL_PNL]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.REQ_PNL_SINGLE]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.CANCEL_PNL_SINGLE]: MIN_SERVER_VER_PROTOBUF_SCAN_DATA,
+ [OUT.REQ_FA]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.REPLACE_FA]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.EXERCISE_OPTIONS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.REQ_CALC_IMPLIED_VOLAT]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.CANCEL_CALC_IMPLIED_VOLAT]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.REQ_CALC_OPTION_PRICE]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.CANCEL_CALC_OPTION_PRICE]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1,
+ [OUT.REQ_SEC_DEF_OPT_PARAMS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_SOFT_DOLLAR_TIERS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_FAMILY_CODES]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_MATCHING_SYMBOLS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_SMART_COMPONENTS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_MARKET_RULE]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_USER_INFO]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2,
+ [OUT.REQ_IDS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.REQ_CURRENT_TIME]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.REQ_CURRENT_TIME_IN_MILLIS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.START_API]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.SET_SERVER_LOGLEVEL]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.VERIFY_REQUEST]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.VERIFY_MESSAGE]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.QUERY_DISPLAY_GROUPS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.SUBSCRIBE_TO_GROUP_EVENTS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.UPDATE_DISPLAY_GROUP]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.UNSUBSCRIBE_FROM_GROUP_EVENTS]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+ [OUT.REQ_MKT_DEPTH_EXCHANGES]: MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3,
+}
+
+// --- Data classes ---
+
+export class BarData {
+ date = ''
+ open = 0.0
+ high = 0.0
+ low = 0.0
+ close = 0.0
+ volume: Decimal = UNSET_DECIMAL
+ wap: Decimal = UNSET_DECIMAL
+ barCount = 0
+
+ toString(): string {
+ return (
+ `Date: ${this.date}, ` +
+ `Open: ${floatMaxString(this.open)}, ` +
+ `High: ${floatMaxString(this.high)}, ` +
+ `Low: ${floatMaxString(this.low)}, ` +
+ `Close: ${floatMaxString(this.close)}, ` +
+ `Volume: ${decimalMaxString(this.volume)}, ` +
+ `WAP: ${decimalMaxString(this.wap)}, ` +
+ `BarCount: ${intMaxString(this.barCount)}`
+ )
+ }
+}
+
+export class RealTimeBar {
+ time: number
+ endTime: number
+ open_: number
+ high: number
+ low: number
+ close: number
+ volume: Decimal
+ wap: Decimal
+ count: number
+
+ constructor(
+ time = 0,
+ endTime = -1,
+ open_ = 0.0,
+ high = 0.0,
+ low = 0.0,
+ close = 0.0,
+ volume: Decimal = UNSET_DECIMAL,
+ wap: Decimal = UNSET_DECIMAL,
+ count = 0,
+ ) {
+ this.time = time
+ this.endTime = endTime
+ this.open_ = open_
+ this.high = high
+ this.low = low
+ this.close = close
+ this.volume = volume
+ this.wap = wap
+ this.count = count
+ }
+
+ toString(): string {
+ return (
+ `Time: ${intMaxString(this.time)}, Open: ${floatMaxString(this.open_)}, ` +
+ `High: ${floatMaxString(this.high)}, Low: ${floatMaxString(this.low)}, ` +
+ `Close: ${floatMaxString(this.close)}, Volume: ${decimalMaxString(this.volume)}, ` +
+ `WAP: ${decimalMaxString(this.wap)}, Count: ${intMaxString(this.count)}`
+ )
+ }
+}
+
+export class HistogramData {
+ price = 0.0
+ size: Decimal = UNSET_DECIMAL
+
+ toString(): string {
+ return `Price: ${floatMaxString(this.price)}, Size: ${decimalMaxString(this.size)}`
+ }
+}
+
+export class NewsProvider {
+ code = ''
+ name = ''
+
+ toString(): string {
+ return `Code: ${this.code}, Name: ${this.name}`
+ }
+}
+
+export class DepthMktDataDescription {
+ exchange = ''
+ secType = ''
+ listingExch = ''
+ serviceDataType = ''
+ aggGroup: number = UNSET_INTEGER
+
+ toString(): string {
+ const aggGroup = this.aggGroup !== UNSET_INTEGER ? intMaxString(this.aggGroup) : ''
+ return (
+ `Exchange: ${this.exchange}, SecType: ${this.secType}, ` +
+ `ListingExchange: ${this.listingExch}, ServiceDataType: ${this.serviceDataType}, ` +
+ `AggGroup: ${aggGroup}, `
+ )
+ }
+}
+
+export class SmartComponent {
+ bitNumber = 0
+ exchange = ''
+ exchangeLetter = ''
+
+ toString(): string {
+ return `BitNumber: ${this.bitNumber}, Exchange: ${this.exchange}, ExchangeLetter: ${this.exchangeLetter}`
+ }
+}
+
+export class TickAttrib {
+ canAutoExecute = false
+ pastLimit = false
+ preOpen = false
+
+ toString(): string {
+ return `CanAutoExecute: ${+this.canAutoExecute}, PastLimit: ${+this.pastLimit}, PreOpen: ${+this.preOpen}`
+ }
+}
+
+export class TickAttribBidAsk {
+ bidPastLow = false
+ askPastHigh = false
+
+ toString(): string {
+ return `BidPastLow: ${+this.bidPastLow}, AskPastHigh: ${+this.askPastHigh}`
+ }
+}
+
+export class TickAttribLast {
+ pastLimit = false
+ unreported = false
+
+ toString(): string {
+ return `PastLimit: ${+this.pastLimit}, Unreported: ${+this.unreported}`
+ }
+}
+
+export class FamilyCode {
+ accountID = ''
+ familyCodeStr = ''
+
+ toString(): string {
+ return `AccountId: ${this.accountID}, FamilyCodeStr: ${this.familyCodeStr}`
+ }
+}
+
+export class PriceIncrement {
+ lowEdge = 0.0
+ increment = 0.0
+
+ toString(): string {
+ return `LowEdge: ${floatMaxString(this.lowEdge)}, Increment: ${floatMaxString(this.increment)}`
+ }
+}
+
+export class HistoricalTick {
+ time = 0
+ price = 0.0
+ size: Decimal = UNSET_DECIMAL
+
+ toString(): string {
+ return `Time: ${intMaxString(this.time)}, Price: ${floatMaxString(this.price)}, Size: ${decimalMaxString(this.size)}`
+ }
+}
+
+export class HistoricalTickBidAsk {
+ time = 0
+ tickAttribBidAsk: TickAttribBidAsk = new TickAttribBidAsk()
+ priceBid = 0.0
+ priceAsk = 0.0
+ sizeBid: Decimal = UNSET_DECIMAL
+ sizeAsk: Decimal = UNSET_DECIMAL
+
+ toString(): string {
+ return (
+ `Time: ${intMaxString(this.time)}, ` +
+ `TickAttriBidAsk: ${this.tickAttribBidAsk.toString()}, ` +
+ `PriceBid: ${floatMaxString(this.priceBid)}, ` +
+ `PriceAsk: ${floatMaxString(this.priceAsk)}, ` +
+ `SizeBid: ${decimalMaxString(this.sizeBid)}, ` +
+ `SizeAsk: ${decimalMaxString(this.sizeAsk)}`
+ )
+ }
+}
+
+export class HistoricalTickLast {
+ time = 0
+ tickAttribLast: TickAttribLast = new TickAttribLast()
+ price = 0.0
+ size: Decimal = UNSET_DECIMAL
+ exchange = ''
+ specialConditions = ''
+
+ toString(): string {
+ return (
+ `Time: ${intMaxString(this.time)}, ` +
+ `TickAttribLast: ${this.tickAttribLast.toString()}, ` +
+ `Price: ${floatMaxString(this.price)}, ` +
+ `Size: ${decimalMaxString(this.size)}, ` +
+ `Exchange: ${this.exchange}, ` +
+ `SpecialConditions: ${this.specialConditions}`
+ )
+ }
+}
+
+export class HistoricalSession {
+ startDateTime = ''
+ endDateTime = ''
+ refDate = ''
+
+ toString(): string {
+ return `Start: ${this.startDateTime}, End: ${this.endDateTime}, Ref Date: ${this.refDate}`
+ }
+}
+
+export class WshEventData {
+ conId: number = UNSET_INTEGER
+ filter = ''
+ fillWatchlist = false
+ fillPortfolio = false
+ fillCompetitors = false
+ startDate = ''
+ endDate = ''
+ totalLimit: number = UNSET_INTEGER
+
+ toString(): string {
+ return (
+ `WshEventData. ConId: ${intMaxString(this.conId)}, ` +
+ `Filter: ${this.filter}, ` +
+ `Fill Watchlist: ${+this.fillWatchlist}, ` +
+ `Fill Portfolio: ${+this.fillPortfolio}, ` +
+ `Fill Competitors: ${+this.fillCompetitors}`
+ )
+ }
+}
diff --git a/packages/ibkr/src/connection.ts b/packages/ibkr/src/connection.ts
new file mode 100644
index 00000000..db40ee21
--- /dev/null
+++ b/packages/ibkr/src/connection.ts
@@ -0,0 +1,103 @@
+/**
+ * Thin wrapper around a TCP socket for TWS API communication.
+ * Mirrors: ibapi/connection.py
+ *
+ * Node.js adaptation: no threading.Lock needed (single-threaded event loop).
+ * Python's blocking recv with timeout → Node's event-driven socket.
+ */
+
+import net from 'node:net'
+import { EventEmitter } from 'node:events'
+import { NO_VALID_ID } from './const.js'
+import { FAIL_CREATE_SOCK, CONNECT_FAIL } from './errors.js'
+import { currentTimeMillis } from './utils.js'
+
+export interface ConnectionWrapper {
+ error(reqId: number, errorTime: number, errorCode: number, errorString: string, advancedOrderRejectJson?: string): void
+ connectionClosed(): void
+}
+
+export class Connection extends EventEmitter {
+ host: string
+ port: number
+ socket: net.Socket | null = null
+ wrapper: ConnectionWrapper | null = null
+ private _buffer: Buffer = Buffer.alloc(0)
+
+ constructor(host: string, port: number) {
+ super()
+ this.host = host
+ this.port = port
+ }
+
+ connect(): Promise {
+ return new Promise((resolve, reject) => {
+ try {
+ this.socket = new net.Socket()
+ } catch {
+ if (this.wrapper) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg())
+ }
+ return reject(new Error(FAIL_CREATE_SOCK.msg()))
+ }
+
+ this.socket.on('data', (data: Buffer) => {
+ this._buffer = Buffer.concat([this._buffer, data])
+ this.emit('data')
+ })
+
+ this.socket.on('close', () => {
+ this.socket = null
+ if (this.wrapper) {
+ this.wrapper.connectionClosed()
+ }
+ })
+
+ this.socket.on('error', (err: Error) => {
+ this.emit('error', err)
+ })
+
+ this.socket.connect(this.port, this.host, () => {
+ resolve()
+ })
+
+ this.socket.once('error', (err: Error) => {
+ if (this.wrapper) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), CONNECT_FAIL.code(), CONNECT_FAIL.msg())
+ }
+ reject(err)
+ })
+ })
+ }
+
+ disconnect(): void {
+ if (this.socket !== null) {
+ this.socket.destroy()
+ this.socket = null
+ if (this.wrapper) {
+ this.wrapper.connectionClosed()
+ }
+ }
+ }
+
+ isConnected(): boolean {
+ return this.socket !== null
+ }
+
+ sendMsg(msg: Buffer): boolean {
+ if (!this.isConnected() || !this.socket) {
+ return false
+ }
+ return this.socket.write(msg)
+ }
+
+ /**
+ * Consume buffered data. Returns current buffer and resets it.
+ * Used by the reader to get accumulated socket data.
+ */
+ consumeBuffer(): Buffer {
+ const buf = this._buffer
+ this._buffer = Buffer.alloc(0)
+ return buf
+ }
+}
diff --git a/packages/ibkr/src/const.ts b/packages/ibkr/src/const.ts
new file mode 100644
index 00000000..7711e741
--- /dev/null
+++ b/packages/ibkr/src/const.ts
@@ -0,0 +1,15 @@
+/**
+ * TWS API constants — sentinel values for "unset" state.
+ * Mirrors: ibapi/const.py
+ */
+
+import Decimal from 'decimal.js'
+
+export const NO_VALID_ID = -1
+export const MAX_MSG_LEN = 0xffffff // 16MB - 1byte
+export const UNSET_INTEGER = 2 ** 31 - 1
+export const UNSET_DOUBLE = Number.MAX_VALUE
+export const UNSET_LONG = BigInt(2 ** 63) - 1n
+export const UNSET_DECIMAL = new Decimal('170141183460469231731687303715884105727') // 2^127 - 1
+export const DOUBLE_INFINITY = Infinity
+export const INFINITY_STR = 'Infinity'
diff --git a/packages/ibkr/src/contract.ts b/packages/ibkr/src/contract.ts
new file mode 100644
index 00000000..35fcfc01
--- /dev/null
+++ b/packages/ibkr/src/contract.ts
@@ -0,0 +1,265 @@
+/**
+ * Mirrors: ibapi/contract.py
+ */
+
+import Decimal from 'decimal.js'
+import { UNSET_DECIMAL, UNSET_DOUBLE, UNSET_INTEGER } from './const.js'
+import type { IneligibilityReason } from './ineligibility-reason.js'
+
+function floatMaxString(val: number): string { return val === UNSET_DOUBLE ? '' : String(val) }
+function intMaxString(val: number): string { return val === UNSET_INTEGER ? '' : String(val) }
+function decimalMaxString(val: Decimal): string { return val.equals(UNSET_DECIMAL) ? '' : val.toString() }
+
+export const SAME_POS = 0
+export const OPEN_POS = 1
+export const CLOSE_POS = 2
+export const UNKNOWN_POS = 3
+
+export class ComboLeg {
+ conId: number = 0
+ ratio: number = 0
+ action: string = ''
+ exchange: string = ''
+ openClose: number = 0
+ shortSaleSlot: number = 0
+ designatedLocation: string = ''
+ exemptCode: number = -1
+
+ toString(): string {
+ return [
+ intMaxString(this.conId),
+ intMaxString(this.ratio),
+ String(this.action),
+ String(this.exchange),
+ intMaxString(this.openClose),
+ intMaxString(this.shortSaleSlot),
+ String(this.designatedLocation),
+ intMaxString(this.exemptCode),
+ ].join(',')
+ }
+}
+
+export class DeltaNeutralContract {
+ conId: number = 0
+ delta: number = 0.0
+ price: number = 0.0
+
+ toString(): string {
+ return [
+ String(this.conId),
+ floatMaxString(this.delta),
+ floatMaxString(this.price),
+ ].join(',')
+ }
+}
+
+export class Contract {
+ conId: number = 0
+ symbol: string = ''
+ secType: string = ''
+ lastTradeDateOrContractMonth: string = ''
+ lastTradeDate: string = ''
+ strike: number = UNSET_DOUBLE
+ right: string = ''
+ multiplier: string = ''
+ exchange: string = ''
+ primaryExchange: string = ''
+ currency: string = ''
+ localSymbol: string = ''
+ tradingClass: string = ''
+ includeExpired: boolean = false
+ secIdType: string = ''
+ secId: string = ''
+ description: string = ''
+ issuerId: string = ''
+ comboLegsDescrip: string = ''
+ comboLegs: ComboLeg[] = []
+ deltaNeutralContract: DeltaNeutralContract | null = null
+
+ toString(): string {
+ let s =
+ `ConId: ${intMaxString(this.conId)}, ` +
+ `Symbol: ${this.symbol}, ` +
+ `SecType: ${this.secType}, ` +
+ `LastTradeDateOrContractMonth: ${this.lastTradeDateOrContractMonth}, ` +
+ `Strike: ${floatMaxString(this.strike)}, ` +
+ `Right: ${this.right}, ` +
+ `Multiplier: ${this.multiplier}, ` +
+ `Exchange: ${this.exchange}, ` +
+ `PrimaryExchange: ${this.primaryExchange}, ` +
+ `Currency: ${this.currency}, ` +
+ `LocalSymbol: ${this.localSymbol}, ` +
+ `TradingClass: ${this.tradingClass}, ` +
+ `IncludeExpired: ${this.includeExpired}, ` +
+ `SecIdType: ${this.secIdType}, ` +
+ `SecId: ${this.secId}, ` +
+ `Description: ${this.description}, ` +
+ `IssuerId: ${this.issuerId}`
+
+ s += 'Combo:' + this.comboLegsDescrip
+
+ if (this.comboLegs.length > 0) {
+ for (const leg of this.comboLegs) {
+ s += ';' + leg.toString()
+ }
+ }
+
+ if (this.deltaNeutralContract) {
+ s += ';' + this.deltaNeutralContract.toString()
+ }
+
+ return s
+ }
+}
+
+export const FundAssetType = {
+ NoneItem: ['None', 'None'],
+ Others: ['000', 'Others'],
+ MoneyMarket: ['001', 'Money Market'],
+ FixedIncome: ['002', 'Fixed Income'],
+ MultiAsset: ['003', 'Multi-asset'],
+ Equity: ['004', 'Equity'],
+ Sector: ['005', 'Sector'],
+ Guaranteed: ['006', 'Guaranteed'],
+ Alternative: ['007', 'Alternative'],
+} as const
+
+export const FundDistributionPolicyIndicator = {
+ NoneItem: ['None', 'None'],
+ AccumulationFund: ['N', 'Accumulation Fund'],
+ IncomeFund: ['Y', 'Income Fund'],
+} as const
+
+export type FundAssetTypeValue = (typeof FundAssetType)[keyof typeof FundAssetType]
+export type FundDistributionPolicyIndicatorValue = (typeof FundDistributionPolicyIndicator)[keyof typeof FundDistributionPolicyIndicator]
+
+export class ContractDetails {
+ contract: Contract = new Contract()
+ marketName: string = ''
+ minTick: number = 0.0
+ orderTypes: string = ''
+ validExchanges: string = ''
+ priceMagnifier: number = 0
+ underConId: number = 0
+ longName: string = ''
+ contractMonth: string = ''
+ industry: string = ''
+ category: string = ''
+ subcategory: string = ''
+ timeZoneId: string = ''
+ tradingHours: string = ''
+ liquidHours: string = ''
+ evRule: string = ''
+ evMultiplier: number = 0
+ aggGroup: number = 0
+ underSymbol: string = ''
+ underSecType: string = ''
+ marketRuleIds: string = ''
+ secIdList: Array<{ tag: string; value: string }> | null = null
+ realExpirationDate: string = ''
+ lastTradeTime: string = ''
+ stockType: string = ''
+ minSize: Decimal = UNSET_DECIMAL
+ sizeIncrement: Decimal = UNSET_DECIMAL
+ suggestedSizeIncrement: Decimal = UNSET_DECIMAL
+ minAlgoSize: Decimal = UNSET_DECIMAL
+ lastPricePrecision: Decimal = UNSET_DECIMAL
+ lastSizePrecision: Decimal = UNSET_DECIMAL
+ // BOND values
+ cusip: string = ''
+ ratings: string = ''
+ descAppend: string = ''
+ bondType: string = ''
+ couponType: string = ''
+ callable: boolean = false
+ putable: boolean = false
+ coupon: number = 0
+ convertible: boolean = false
+ maturity: string = ''
+ issueDate: string = ''
+ nextOptionDate: string = ''
+ nextOptionType: string = ''
+ nextOptionPartial: boolean = false
+ notes: string = ''
+ // FUND values
+ fundName: string = ''
+ fundFamily: string = ''
+ fundType: string = ''
+ fundFrontLoad: string = ''
+ fundBackLoad: string = ''
+ fundBackLoadTimeInterval: string = ''
+ fundManagementFee: string = ''
+ fundClosed: boolean = false
+ fundClosedForNewInvestors: boolean = false
+ fundClosedForNewMoney: boolean = false
+ fundNotifyAmount: string = ''
+ fundMinimumInitialPurchase: string = ''
+ fundSubsequentMinimumPurchase: string = ''
+ fundBlueSkyStates: string = ''
+ fundBlueSkyTerritories: string = ''
+ fundDistributionPolicyIndicator: FundDistributionPolicyIndicatorValue = FundDistributionPolicyIndicator.NoneItem
+ fundAssetType: FundAssetTypeValue = FundAssetType.NoneItem
+ ineligibilityReasonList: IneligibilityReason[] | null = null
+ eventContract1: string = ''
+ eventContractDescription1: string = ''
+ eventContractDescription2: string = ''
+
+ toString(): string {
+ return [
+ String(this.contract),
+ String(this.marketName),
+ floatMaxString(this.minTick),
+ String(this.orderTypes),
+ String(this.validExchanges),
+ intMaxString(this.priceMagnifier),
+ intMaxString(this.underConId),
+ String(this.longName),
+ String(this.contractMonth),
+ String(this.industry),
+ String(this.category),
+ String(this.subcategory),
+ String(this.timeZoneId),
+ String(this.tradingHours),
+ String(this.liquidHours),
+ String(this.evRule),
+ intMaxString(this.evMultiplier),
+ String(this.underSymbol),
+ String(this.underSecType),
+ String(this.marketRuleIds),
+ intMaxString(this.aggGroup),
+ String(this.secIdList),
+ String(this.realExpirationDate),
+ String(this.stockType),
+ String(this.cusip),
+ String(this.ratings),
+ String(this.descAppend),
+ String(this.bondType),
+ String(this.couponType),
+ String(this.callable),
+ String(this.putable),
+ String(this.coupon),
+ String(this.convertible),
+ String(this.maturity),
+ String(this.issueDate),
+ String(this.nextOptionDate),
+ String(this.nextOptionType),
+ String(this.nextOptionPartial),
+ String(this.notes),
+ decimalMaxString(this.minSize),
+ decimalMaxString(this.sizeIncrement),
+ decimalMaxString(this.suggestedSizeIncrement),
+ decimalMaxString(this.minAlgoSize),
+ decimalMaxString(this.lastPricePrecision),
+ decimalMaxString(this.lastSizePrecision),
+ String(this.ineligibilityReasonList),
+ String(this.eventContract1),
+ String(this.eventContractDescription1),
+ String(this.eventContractDescription2),
+ ].join(',')
+ }
+}
+
+export class ContractDescription {
+ contract: Contract = new Contract()
+ derivativeSecTypes: string[] = []
+}
diff --git a/packages/ibkr/src/decoder/account.ts b/packages/ibkr/src/decoder/account.ts
new file mode 100644
index 00000000..4fc88ef3
--- /dev/null
+++ b/packages/ibkr/src/decoder/account.ts
@@ -0,0 +1,487 @@
+/**
+ * Account / position decoder handlers — text + protobuf.
+ *
+ * Mirrors: ibapi/decoder.py (account-related process methods)
+ */
+
+import { Decoder } from './base.js'
+import { IN } from '../message.js'
+import { NO_VALID_ID, UNSET_DOUBLE, UNSET_DECIMAL } from '../const.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeDecimal,
+ floatMaxString,
+} from '../utils.js'
+import {
+ MIN_SERVER_VER_UNREALIZED_PNL,
+ MIN_SERVER_VER_REALIZED_PNL,
+} from '../server-versions.js'
+import { Contract } from '../contract.js'
+import Decimal from 'decimal.js'
+
+// Protobuf message types
+import { AccountValue as AccountValueProto } from '../protobuf/AccountValue.js'
+import { PortfolioValue as PortfolioValueProto } from '../protobuf/PortfolioValue.js'
+import { AccountUpdateTime as AccountUpdateTimeProto } from '../protobuf/AccountUpdateTime.js'
+import { AccountDataEnd as AccountDataEndProto } from '../protobuf/AccountDataEnd.js'
+import { ManagedAccounts as ManagedAccountsProto } from '../protobuf/ManagedAccounts.js'
+import { Position as PositionProto } from '../protobuf/Position.js'
+import { PositionEnd as PositionEndProto } from '../protobuf/PositionEnd.js'
+import { AccountSummary as AccountSummaryProto } from '../protobuf/AccountSummary.js'
+import { AccountSummaryEnd as AccountSummaryEndProto } from '../protobuf/AccountSummaryEnd.js'
+import { PositionMulti as PositionMultiProto } from '../protobuf/PositionMulti.js'
+import { PositionMultiEnd as PositionMultiEndProto } from '../protobuf/PositionMultiEnd.js'
+import { AccountUpdateMulti as AccountUpdateMultiProto } from '../protobuf/AccountUpdateMulti.js'
+import { AccountUpdateMultiEnd as AccountUpdateMultiEndProto } from '../protobuf/AccountUpdateMultiEnd.js'
+import { PnL as PnLProto } from '../protobuf/PnL.js'
+import { PnLSingle as PnLSingleProto } from '../protobuf/PnLSingle.js'
+import type { Contract as ContractProto } from '../protobuf/Contract.js'
+
+// ---------------------------------------------------------------------------
+// Helper: convert a protobuf Contract message to our Contract class
+// Mirrors: ibapi/decoder_utils.py decodeContract()
+// ---------------------------------------------------------------------------
+function decodeContractProto(cp: ContractProto): Contract {
+ const c = new Contract()
+ if (cp.conId !== undefined) c.conId = cp.conId
+ if (cp.symbol !== undefined) c.symbol = cp.symbol
+ if (cp.secType !== undefined) c.secType = cp.secType
+ if (cp.lastTradeDateOrContractMonth !== undefined) c.lastTradeDateOrContractMonth = cp.lastTradeDateOrContractMonth
+ if (cp.strike !== undefined) c.strike = cp.strike
+ if (cp.right !== undefined) c.right = cp.right
+ if (cp.multiplier !== undefined) c.multiplier = floatMaxString(cp.multiplier)
+ if (cp.exchange !== undefined) c.exchange = cp.exchange
+ if (cp.currency !== undefined) c.currency = cp.currency
+ if (cp.localSymbol !== undefined) c.localSymbol = cp.localSymbol
+ if (cp.tradingClass !== undefined) c.tradingClass = cp.tradingClass
+ if (cp.comboLegsDescrip !== undefined) c.comboLegsDescrip = cp.comboLegsDescrip
+ if (cp.lastTradeDate !== undefined) c.lastTradeDate = cp.lastTradeDate
+ if (cp.primaryExch !== undefined) c.primaryExchange = cp.primaryExch
+ if (cp.issuerId !== undefined) c.issuerId = cp.issuerId
+ if (cp.description !== undefined) c.description = cp.description
+ return c
+}
+
+// ---------------------------------------------------------------------------
+// Registration
+// ---------------------------------------------------------------------------
+
+export function applyAccountHandlers(decoder: Decoder): void {
+ // ===========================================================================
+ // IN.ACCT_VALUE (6)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCT_VALUE, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const key = decodeStr(fields)
+ const val = decodeStr(fields)
+ const currency = decodeStr(fields)
+ const accountName = decodeStr(fields)
+ d.wrapper.updateAccountValue(key, val, currency, accountName)
+ })
+
+ decoder.registerProto(IN.ACCT_VALUE, (d, buf) => {
+ const proto = AccountValueProto.decode(buf)
+ const key = proto.key ?? ''
+ const value = proto.value ?? ''
+ const currency = proto.currency ?? ''
+ const accountName = proto.accountName ?? ''
+ d.wrapper.updateAccountValue(key, value, currency, accountName)
+ })
+
+ // ===========================================================================
+ // IN.PORTFOLIO_VALUE (7)
+ // ===========================================================================
+
+ decoder.registerText(IN.PORTFOLIO_VALUE, (d, fields) => {
+ decodeInt(fields) // msgId
+ const version = decodeInt(fields)
+
+ const contract = new Contract()
+ contract.conId = decodeInt(fields) // ver 6
+ contract.symbol = decodeStr(fields)
+ contract.secType = decodeStr(fields)
+ contract.lastTradeDateOrContractMonth = decodeStr(fields)
+ contract.strike = decodeFloat(fields)
+ contract.right = decodeStr(fields)
+
+ if (version >= 7) {
+ contract.multiplier = decodeStr(fields)
+ contract.primaryExchange = decodeStr(fields)
+ }
+
+ contract.currency = decodeStr(fields)
+ contract.localSymbol = decodeStr(fields) // ver 2
+ if (version >= 8) {
+ contract.tradingClass = decodeStr(fields)
+ }
+
+ const position = decodeDecimal(fields)
+ const marketPrice = decodeFloat(fields)
+ const marketValue = decodeFloat(fields)
+ const averageCost = decodeFloat(fields) // ver 3
+ const unrealizedPNL = decodeFloat(fields) // ver 3
+ const realizedPNL = decodeFloat(fields) // ver 3
+ const accountName = decodeStr(fields) // ver 4
+
+ if (version === 6 && d.serverVersion === 39) {
+ contract.primaryExchange = decodeStr(fields)
+ }
+
+ d.wrapper.updatePortfolio(
+ contract, position, marketPrice, marketValue,
+ averageCost, unrealizedPNL, realizedPNL, accountName,
+ )
+ })
+
+ decoder.registerProto(IN.PORTFOLIO_VALUE, (d, buf) => {
+ const proto = PortfolioValueProto.decode(buf)
+
+ if (!proto.contract) return
+ const contract = decodeContractProto(proto.contract)
+
+ const position = proto.position !== undefined ? new Decimal(proto.position) : UNSET_DECIMAL
+ const marketPrice = proto.marketPrice ?? 0
+ const marketValue = proto.marketValue ?? 0
+ const averageCost = proto.averageCost ?? 0
+ const unrealizedPNL = proto.unrealizedPNL ?? 0
+ const realizedPNL = proto.realizedPNL ?? 0
+ const accountName = proto.accountName ?? ''
+
+ d.wrapper.updatePortfolio(
+ contract, position, marketPrice, marketValue,
+ averageCost, unrealizedPNL, realizedPNL, accountName,
+ )
+ })
+
+ // ===========================================================================
+ // IN.ACCT_UPDATE_TIME (8)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCT_UPDATE_TIME, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const timeStamp = decodeStr(fields)
+ d.wrapper.updateAccountTime(timeStamp)
+ })
+
+ decoder.registerProto(IN.ACCT_UPDATE_TIME, (d, buf) => {
+ const proto = AccountUpdateTimeProto.decode(buf)
+ const timeStamp = proto.timeStamp ?? ''
+ d.wrapper.updateAccountTime(timeStamp)
+ })
+
+ // ===========================================================================
+ // IN.ACCT_DOWNLOAD_END (54)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCT_DOWNLOAD_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const accountName = decodeStr(fields)
+ d.wrapper.accountDownloadEnd(accountName)
+ })
+
+ decoder.registerProto(IN.ACCT_DOWNLOAD_END, (d, buf) => {
+ const proto = AccountDataEndProto.decode(buf)
+ const accountName = proto.accountName ?? ''
+ d.wrapper.accountDownloadEnd(accountName)
+ })
+
+ // ===========================================================================
+ // IN.MANAGED_ACCTS (15)
+ // ===========================================================================
+
+ decoder.registerText(IN.MANAGED_ACCTS, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const accountsList = decodeStr(fields)
+ d.wrapper.managedAccounts(accountsList)
+ })
+
+ decoder.registerProto(IN.MANAGED_ACCTS, (d, buf) => {
+ const proto = ManagedAccountsProto.decode(buf)
+ d.wrapper.managedAccounts(proto.accountsList ?? '')
+ })
+
+ // ===========================================================================
+ // IN.POSITION_DATA (61)
+ // ===========================================================================
+
+ decoder.registerText(IN.POSITION_DATA, (d, fields) => {
+ decodeInt(fields) // msgId
+ const version = decodeInt(fields)
+
+ const account = decodeStr(fields)
+
+ const contract = new Contract()
+ contract.conId = decodeInt(fields)
+ contract.symbol = decodeStr(fields)
+ contract.secType = decodeStr(fields)
+ contract.lastTradeDateOrContractMonth = decodeStr(fields)
+ contract.strike = decodeFloat(fields)
+ contract.right = decodeStr(fields)
+ contract.multiplier = decodeStr(fields)
+ contract.exchange = decodeStr(fields)
+ contract.currency = decodeStr(fields)
+ contract.localSymbol = decodeStr(fields)
+ if (version >= 2) {
+ contract.tradingClass = decodeStr(fields)
+ }
+
+ const position = decodeDecimal(fields)
+
+ let avgCost = 0.0
+ if (version >= 3) {
+ avgCost = decodeFloat(fields)
+ }
+
+ d.wrapper.position(account, contract, position, avgCost)
+ })
+
+ decoder.registerProto(IN.POSITION_DATA, (d, buf) => {
+ const proto = PositionProto.decode(buf)
+
+ if (!proto.contract) return
+ const contract = decodeContractProto(proto.contract)
+
+ const position = proto.position !== undefined ? new Decimal(proto.position) : UNSET_DECIMAL
+ const avgCost = proto.avgCost ?? 0
+ const account = proto.account ?? ''
+
+ d.wrapper.position(account, contract, position, avgCost)
+ })
+
+ // ===========================================================================
+ // IN.POSITION_END (62)
+ // ===========================================================================
+
+ decoder.registerText(IN.POSITION_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ d.wrapper.positionEnd()
+ })
+
+ decoder.registerProto(IN.POSITION_END, (_d, buf) => {
+ PositionEndProto.decode(buf)
+ _d.wrapper.positionEnd()
+ })
+
+ // ===========================================================================
+ // IN.ACCOUNT_SUMMARY (63)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCOUNT_SUMMARY, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const account = decodeStr(fields)
+ const tag = decodeStr(fields)
+ const value = decodeStr(fields)
+ const currency = decodeStr(fields)
+ d.wrapper.accountSummary(reqId, account, tag, value, currency)
+ })
+
+ decoder.registerProto(IN.ACCOUNT_SUMMARY, (d, buf) => {
+ const proto = AccountSummaryProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const account = proto.account ?? ''
+ const tag = proto.tag ?? ''
+ const value = proto.value ?? ''
+ const currency = proto.currency ?? ''
+ d.wrapper.accountSummary(reqId, account, tag, value, currency)
+ })
+
+ // ===========================================================================
+ // IN.ACCOUNT_SUMMARY_END (64)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCOUNT_SUMMARY_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ d.wrapper.accountSummaryEnd(reqId)
+ })
+
+ decoder.registerProto(IN.ACCOUNT_SUMMARY_END, (d, buf) => {
+ const proto = AccountSummaryEndProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ d.wrapper.accountSummaryEnd(reqId)
+ })
+
+ // ===========================================================================
+ // IN.POSITION_MULTI (71)
+ // ===========================================================================
+
+ decoder.registerText(IN.POSITION_MULTI, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const account = decodeStr(fields)
+
+ const contract = new Contract()
+ contract.conId = decodeInt(fields)
+ contract.symbol = decodeStr(fields)
+ contract.secType = decodeStr(fields)
+ contract.lastTradeDateOrContractMonth = decodeStr(fields)
+ contract.strike = decodeFloat(fields)
+ contract.right = decodeStr(fields)
+ contract.multiplier = decodeStr(fields)
+ contract.exchange = decodeStr(fields)
+ contract.currency = decodeStr(fields)
+ contract.localSymbol = decodeStr(fields)
+ contract.tradingClass = decodeStr(fields)
+ const position = decodeDecimal(fields)
+ const avgCost = decodeFloat(fields)
+ const modelCode = decodeStr(fields)
+
+ d.wrapper.positionMulti(reqId, account, modelCode, contract, position, avgCost)
+ })
+
+ decoder.registerProto(IN.POSITION_MULTI, (d, buf) => {
+ const proto = PositionMultiProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const account = proto.account ?? ''
+ const modelCode = proto.modelCode ?? ''
+
+ if (!proto.contract) return
+ const contract = decodeContractProto(proto.contract)
+
+ const position = proto.position !== undefined ? new Decimal(proto.position) : UNSET_DECIMAL
+ const avgCost = proto.avgCost ?? 0
+
+ d.wrapper.positionMulti(reqId, account, modelCode, contract, position, avgCost)
+ })
+
+ // ===========================================================================
+ // IN.POSITION_MULTI_END (72)
+ // ===========================================================================
+
+ decoder.registerText(IN.POSITION_MULTI_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ d.wrapper.positionMultiEnd(reqId)
+ })
+
+ decoder.registerProto(IN.POSITION_MULTI_END, (d, buf) => {
+ const proto = PositionMultiEndProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ d.wrapper.positionMultiEnd(reqId)
+ })
+
+ // ===========================================================================
+ // IN.ACCOUNT_UPDATE_MULTI (73)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCOUNT_UPDATE_MULTI, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const account = decodeStr(fields)
+ const modelCode = decodeStr(fields)
+ const key = decodeStr(fields)
+ const value = decodeStr(fields)
+ const currency = decodeStr(fields)
+ d.wrapper.accountUpdateMulti(reqId, account, modelCode, key, value, currency)
+ })
+
+ decoder.registerProto(IN.ACCOUNT_UPDATE_MULTI, (d, buf) => {
+ const proto = AccountUpdateMultiProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const account = proto.account ?? ''
+ const modelCode = proto.modelCode ?? ''
+ const key = proto.key ?? ''
+ const value = proto.value ?? ''
+ const currency = proto.currency ?? ''
+ d.wrapper.accountUpdateMulti(reqId, account, modelCode, key, value, currency)
+ })
+
+ // ===========================================================================
+ // IN.ACCOUNT_UPDATE_MULTI_END (74)
+ // ===========================================================================
+
+ decoder.registerText(IN.ACCOUNT_UPDATE_MULTI_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ d.wrapper.accountUpdateMultiEnd(reqId)
+ })
+
+ decoder.registerProto(IN.ACCOUNT_UPDATE_MULTI_END, (d, buf) => {
+ const proto = AccountUpdateMultiEndProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ d.wrapper.accountUpdateMultiEnd(reqId)
+ })
+
+ // ===========================================================================
+ // IN.PNL (94)
+ // ===========================================================================
+
+ decoder.registerText(IN.PNL, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const dailyPnL = decodeFloat(fields)
+ let unrealizedPnL: number | null = null
+ let realizedPnL: number | null = null
+
+ if (d.serverVersion >= MIN_SERVER_VER_UNREALIZED_PNL) {
+ unrealizedPnL = decodeFloat(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_REALIZED_PNL) {
+ realizedPnL = decodeFloat(fields)
+ }
+
+ d.wrapper.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL)
+ })
+
+ decoder.registerProto(IN.PNL, (d, buf) => {
+ const proto = PnLProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const dailyPnL = proto.dailyPnL ?? UNSET_DOUBLE
+ const unrealizedPnL = proto.unrealizedPnL ?? UNSET_DOUBLE
+ const realizedPnL = proto.realizedPnL ?? UNSET_DOUBLE
+ d.wrapper.pnl(reqId, dailyPnL, unrealizedPnL, realizedPnL)
+ })
+
+ // ===========================================================================
+ // IN.PNL_SINGLE (95)
+ // ===========================================================================
+
+ decoder.registerText(IN.PNL_SINGLE, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const pos = decodeDecimal(fields)
+ const dailyPnL = decodeFloat(fields)
+ let unrealizedPnL: number | null = null
+ let realizedPnL: number | null = null
+
+ if (d.serverVersion >= MIN_SERVER_VER_UNREALIZED_PNL) {
+ unrealizedPnL = decodeFloat(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_REALIZED_PNL) {
+ realizedPnL = decodeFloat(fields)
+ }
+
+ const value = decodeFloat(fields)
+
+ d.wrapper.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value)
+ })
+
+ decoder.registerProto(IN.PNL_SINGLE, (d, buf) => {
+ const proto = PnLSingleProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const pos = proto.position !== undefined ? new Decimal(proto.position) : UNSET_DECIMAL
+ const dailyPnL = proto.dailyPnL ?? UNSET_DOUBLE
+ const unrealizedPnL = proto.unrealizedPnL ?? UNSET_DOUBLE
+ const realizedPnL = proto.realizedPnL ?? UNSET_DOUBLE
+ const value = proto.value ?? UNSET_DOUBLE
+ d.wrapper.pnlSingle(reqId, pos, dailyPnL, unrealizedPnL, realizedPnL, value)
+ })
+}
diff --git a/packages/ibkr/src/decoder/base.ts b/packages/ibkr/src/decoder/base.ts
new file mode 100644
index 00000000..2ee717d1
--- /dev/null
+++ b/packages/ibkr/src/decoder/base.ts
@@ -0,0 +1,92 @@
+/**
+ * Decoder base — class skeleton, dispatch tables, interpret/processProtoBuf.
+ *
+ * Actual handler methods are registered by sibling modules (market-data, orders, etc.)
+ * via the register* helpers exported here.
+ */
+
+import type { EWrapper } from '../wrapper.js'
+import { NO_VALID_ID } from '../const.js'
+import { BadMessage, currentTimeMillis } from '../utils.js'
+import { BAD_MESSAGE, UNKNOWN_ID } from '../errors.js'
+
+export type TextHandler = (decoder: Decoder, fields: Iterator) => void
+export type ProtoHandler = (decoder: Decoder, buf: Buffer) => void
+
+export class Decoder {
+ wrapper: EWrapper
+ serverVersion: number
+
+ private readonly msgId2textHandler = new Map()
+ private readonly msgId2protoHandler = new Map()
+
+ constructor(wrapper: EWrapper, serverVersion: number) {
+ this.wrapper = wrapper
+ this.serverVersion = serverVersion
+ }
+
+ /** Register a text-protocol handler for a given IN message id. */
+ registerText(msgId: number, handler: TextHandler): void {
+ this.msgId2textHandler.set(msgId, handler)
+ }
+
+ /** Register a protobuf handler for a given IN message id. */
+ registerProto(msgId: number, handler: ProtoHandler): void {
+ this.msgId2protoHandler.set(msgId, handler)
+ }
+
+ /**
+ * Dispatch a text-protocol message.
+ * Mirrors: ibapi/decoder.py interpret()
+ */
+ interpret(fields: string[], msgId?: number): void {
+ if (msgId === undefined) {
+ msgId = parseInt(fields[0] || '0', 10)
+ }
+ if (msgId === 0) return
+
+ const handler = this.msgId2textHandler.get(msgId)
+ if (!handler) {
+ this.wrapper.error(NO_VALID_ID, currentTimeMillis(), UNKNOWN_ID.code(), UNKNOWN_ID.msg(), '')
+ return
+ }
+
+ try {
+ handler(this, fields[Symbol.iterator]())
+ } catch (e) {
+ if (e instanceof BadMessage) {
+ this.wrapper.error(
+ NO_VALID_ID, currentTimeMillis(),
+ BAD_MESSAGE.code(), BAD_MESSAGE.msg() + fields.join(','), '',
+ )
+ }
+ throw e
+ }
+ }
+
+ /**
+ * Dispatch a protobuf-encoded message.
+ * Mirrors: ibapi/decoder.py processProtoBuf()
+ */
+ processProtoBuf(protoBuf: Buffer, msgId: number): void {
+ if (msgId === 0) return
+
+ const handler = this.msgId2protoHandler.get(msgId)
+ if (!handler) {
+ console.log(`[ibkr] unhandled protobuf message: msgId=${msgId}, len=${protoBuf.length}`)
+ return
+ }
+
+ try {
+ handler(this, protoBuf)
+ } catch (e) {
+ if (e instanceof BadMessage) {
+ this.wrapper.error(
+ NO_VALID_ID, currentTimeMillis(),
+ BAD_MESSAGE.code(), BAD_MESSAGE.msg() + `protobuf msgId=${msgId}`, '',
+ )
+ }
+ throw e
+ }
+ }
+}
diff --git a/packages/ibkr/src/decoder/contract.ts b/packages/ibkr/src/decoder/contract.ts
new file mode 100644
index 00000000..4dc06cbc
--- /dev/null
+++ b/packages/ibkr/src/decoder/contract.ts
@@ -0,0 +1,682 @@
+/**
+ * Contract-related decoder handlers (text + protobuf).
+ *
+ * Message types:
+ * IN.CONTRACT_DATA (10)
+ * IN.BOND_CONTRACT_DATA (18)
+ * IN.CONTRACT_DATA_END (52)
+ * IN.SYMBOL_SAMPLES (79)
+ * IN.DELTA_NEUTRAL_VALIDATION (56)
+ * IN.MARKET_RULE (93)
+ *
+ * Mirrors: ibapi/decoder.py (text handlers)
+ * ibapi/decoder.py + ibapi/decoder_utils.py (protobuf handlers)
+ */
+
+import Decimal from 'decimal.js'
+import type { Decoder } from './base.js'
+import { IN } from '../message.js'
+import {
+ Contract,
+ ContractDetails,
+ ContractDescription,
+ DeltaNeutralContract,
+ ComboLeg,
+ FundDistributionPolicyIndicator,
+ FundAssetType,
+} from '../contract.js'
+import { TagValue } from '../tag-value.js'
+import { PriceIncrement } from '../common.js'
+import { IneligibilityReason } from '../ineligibility-reason.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeBool,
+ decodeDecimal,
+} from '../utils.js'
+import {
+ MIN_SERVER_VER_SIZE_RULES,
+ MIN_SERVER_VER_MD_SIZE_MULTIPLIER,
+ MIN_SERVER_VER_ENCODE_MSG_ASCII7,
+ MIN_SERVER_VER_AGG_GROUP,
+ MIN_SERVER_VER_UNDERLYING_INFO,
+ MIN_SERVER_VER_MARKET_RULES,
+ MIN_SERVER_VER_REAL_EXPIRATION_DATE,
+ MIN_SERVER_VER_STOCK_TYPE,
+ MIN_SERVER_VER_FRACTIONAL_SIZE_SUPPORT,
+ MIN_SERVER_VER_FUND_DATA_FIELDS,
+ MIN_SERVER_VER_INELIGIBILITY_REASONS,
+ MIN_SERVER_VER_LAST_TRADE_DATE,
+ MIN_SERVER_VER_BOND_TRADING_HOURS,
+ MIN_SERVER_VER_BOND_ISSUERID,
+} from '../server-versions.js'
+import { NO_VALID_ID } from '../const.js'
+
+// Protobuf message types
+import { ContractData as ContractDataProto } from '../protobuf/ContractData.js'
+import { ContractDataEnd as ContractDataEndProto } from '../protobuf/ContractDataEnd.js'
+import { SymbolSamples as SymbolSamplesProto } from '../protobuf/SymbolSamples.js'
+import { MarketRule as MarketRuleProto } from '../protobuf/MarketRule.js'
+import type { Contract as ContractProto } from '../protobuf/Contract.js'
+import type { ContractDetails as ContractDetailsProto } from '../protobuf/ContractDetails.js'
+
+// ---------------------------------------------------------------------------
+// Helpers
+// ---------------------------------------------------------------------------
+
+function getEnumTypeFromString(
+ enumObj: Record,
+ code: string,
+): readonly [string, string] {
+ for (const val of Object.values(enumObj)) {
+ if (val[0] === code) return val
+ }
+ return enumObj['NoneItem'] ?? ['None', 'None']
+}
+
+function setLastTradeDate(
+ lastTradeDateOrContractMonth: string,
+ contract: ContractDetails,
+ isBond: boolean,
+): void {
+ if (!lastTradeDateOrContractMonth) return
+ const parts = lastTradeDateOrContractMonth.includes('-')
+ ? lastTradeDateOrContractMonth.split('-')
+ : lastTradeDateOrContractMonth.split(/\s+/)
+ if (parts.length > 0) {
+ if (isBond) {
+ contract.maturity = parts[0]
+ } else {
+ contract.contract.lastTradeDateOrContractMonth = parts[0]
+ }
+ }
+ if (parts.length > 1) {
+ contract.lastTradeTime = parts[1]
+ }
+ if (isBond && parts.length > 2) {
+ contract.timeZoneId = parts[2]
+ }
+}
+
+function readLastTradeDate(
+ fields: Iterator,
+ contract: ContractDetails,
+ isBond: boolean,
+): void {
+ const lastTradeDateOrContractMonth = decodeStr(fields)
+ setLastTradeDate(lastTradeDateOrContractMonth, contract, isBond)
+}
+
+// ---------------------------------------------------------------------------
+// Protobuf conversion helpers (mirrors decoder_utils.py)
+// ---------------------------------------------------------------------------
+
+function decodeContractFromProto(proto: ContractProto): Contract {
+ const c = new Contract()
+ if (proto.conId !== undefined) c.conId = proto.conId
+ if (proto.symbol !== undefined) c.symbol = proto.symbol
+ if (proto.secType !== undefined) c.secType = proto.secType
+ if (proto.lastTradeDateOrContractMonth !== undefined) c.lastTradeDateOrContractMonth = proto.lastTradeDateOrContractMonth
+ if (proto.strike !== undefined) c.strike = proto.strike
+ if (proto.right !== undefined) c.right = proto.right
+ if (proto.multiplier !== undefined) c.multiplier = String(proto.multiplier)
+ if (proto.exchange !== undefined) c.exchange = proto.exchange
+ if (proto.currency !== undefined) c.currency = proto.currency
+ if (proto.localSymbol !== undefined) c.localSymbol = proto.localSymbol
+ if (proto.tradingClass !== undefined) c.tradingClass = proto.tradingClass
+ if (proto.comboLegsDescrip !== undefined) c.comboLegsDescrip = proto.comboLegsDescrip
+
+ // combo legs
+ if (proto.comboLegs && proto.comboLegs.length > 0) {
+ c.comboLegs = proto.comboLegs.map((lp) => {
+ const leg = new ComboLeg()
+ if (lp.conId !== undefined) leg.conId = lp.conId
+ if (lp.ratio !== undefined) leg.ratio = lp.ratio
+ if (lp.action !== undefined) leg.action = lp.action
+ if (lp.exchange !== undefined) leg.exchange = lp.exchange
+ if (lp.openClose !== undefined) leg.openClose = lp.openClose
+ if (lp.shortSalesSlot !== undefined) leg.shortSaleSlot = lp.shortSalesSlot
+ if (lp.designatedLocation !== undefined) leg.designatedLocation = lp.designatedLocation
+ if (lp.exemptCode !== undefined) leg.exemptCode = lp.exemptCode
+ return leg
+ })
+ }
+
+ // delta neutral contract
+ if (proto.deltaNeutralContract !== undefined) {
+ const dnc = new DeltaNeutralContract()
+ if (proto.deltaNeutralContract.conId !== undefined) dnc.conId = proto.deltaNeutralContract.conId
+ if (proto.deltaNeutralContract.delta !== undefined) dnc.delta = proto.deltaNeutralContract.delta
+ if (proto.deltaNeutralContract.price !== undefined) dnc.price = proto.deltaNeutralContract.price
+ c.deltaNeutralContract = dnc
+ }
+
+ if (proto.lastTradeDate !== undefined) c.lastTradeDate = proto.lastTradeDate
+ if (proto.primaryExch !== undefined) c.primaryExchange = proto.primaryExch
+ if (proto.issuerId !== undefined) c.issuerId = proto.issuerId
+ if (proto.description !== undefined) c.description = proto.description
+
+ return c
+}
+
+function decodeTagValueList(protoMap: { [key: string]: string }): Array<{ tag: string; value: string }> | null {
+ const list: Array<{ tag: string; value: string }> = []
+ if (protoMap) {
+ for (const [tag, value] of Object.entries(protoMap)) {
+ const tv = new TagValue()
+ tv.tag = tag
+ tv.value = value
+ list.push(tv)
+ }
+ }
+ return list.length > 0 ? list : null
+}
+
+function decodeContractDetailsFromProto(
+ contractProto: ContractProto,
+ detailsProto: ContractDetailsProto,
+ isBond: boolean,
+): ContractDetails {
+ const cd = new ContractDetails()
+ cd.contract = decodeContractFromProto(contractProto)
+
+ if (detailsProto.marketName !== undefined) cd.marketName = detailsProto.marketName
+ if (detailsProto.minTick !== undefined) cd.minTick = parseFloat(detailsProto.minTick)
+ if (detailsProto.priceMagnifier !== undefined) cd.priceMagnifier = detailsProto.priceMagnifier
+ if (detailsProto.orderTypes !== undefined) cd.orderTypes = detailsProto.orderTypes
+ if (detailsProto.validExchanges !== undefined) cd.validExchanges = detailsProto.validExchanges
+ if (detailsProto.underConId !== undefined) cd.underConId = detailsProto.underConId
+ if (detailsProto.longName !== undefined) cd.longName = detailsProto.longName
+ if (detailsProto.contractMonth !== undefined) cd.contractMonth = detailsProto.contractMonth
+ if (detailsProto.industry !== undefined) cd.industry = detailsProto.industry
+ if (detailsProto.category !== undefined) cd.category = detailsProto.category
+ if (detailsProto.subcategory !== undefined) cd.subcategory = detailsProto.subcategory
+ if (detailsProto.timeZoneId !== undefined) cd.timeZoneId = detailsProto.timeZoneId
+ if (detailsProto.tradingHours !== undefined) cd.tradingHours = detailsProto.tradingHours
+ if (detailsProto.liquidHours !== undefined) cd.liquidHours = detailsProto.liquidHours
+ if (detailsProto.evRule !== undefined) cd.evRule = detailsProto.evRule
+ if (detailsProto.evMultiplier !== undefined) cd.evMultiplier = detailsProto.evMultiplier
+
+ const secIdList = decodeTagValueList(detailsProto.secIdList)
+ if (secIdList) cd.secIdList = secIdList
+
+ if (detailsProto.aggGroup !== undefined) cd.aggGroup = detailsProto.aggGroup
+ if (detailsProto.underSymbol !== undefined) cd.underSymbol = detailsProto.underSymbol
+ if (detailsProto.underSecType !== undefined) cd.underSecType = detailsProto.underSecType
+ if (detailsProto.marketRuleIds !== undefined) cd.marketRuleIds = detailsProto.marketRuleIds
+ if (detailsProto.realExpirationDate !== undefined) cd.realExpirationDate = detailsProto.realExpirationDate
+ if (detailsProto.stockType !== undefined) cd.stockType = detailsProto.stockType
+ if (detailsProto.minSize !== undefined) cd.minSize = new Decimal(detailsProto.minSize)
+ if (detailsProto.sizeIncrement !== undefined) cd.sizeIncrement = new Decimal(detailsProto.sizeIncrement)
+ if (detailsProto.suggestedSizeIncrement !== undefined) cd.suggestedSizeIncrement = new Decimal(detailsProto.suggestedSizeIncrement)
+ if (detailsProto.minAlgoSize !== undefined) cd.minAlgoSize = new Decimal(detailsProto.minAlgoSize)
+ if (detailsProto.lastPricePrecision !== undefined) cd.lastPricePrecision = new Decimal(detailsProto.lastPricePrecision)
+ if (detailsProto.lastSizePrecision !== undefined) cd.lastSizePrecision = new Decimal(detailsProto.lastSizePrecision)
+
+ setLastTradeDate(cd.contract.lastTradeDateOrContractMonth, cd, isBond)
+
+ // Bond fields
+ if (detailsProto.cusip !== undefined) cd.cusip = detailsProto.cusip
+ if (detailsProto.ratings !== undefined) cd.ratings = detailsProto.ratings
+ if (detailsProto.descAppend !== undefined) cd.descAppend = detailsProto.descAppend
+ if (detailsProto.bondType !== undefined) cd.bondType = detailsProto.bondType
+ if (detailsProto.coupon !== undefined) cd.coupon = detailsProto.coupon
+ if (detailsProto.couponType !== undefined) cd.couponType = detailsProto.couponType
+ if (detailsProto.callable !== undefined) cd.callable = detailsProto.callable
+ if (detailsProto.puttable !== undefined) cd.putable = detailsProto.puttable
+ if (detailsProto.convertible !== undefined) cd.convertible = detailsProto.convertible
+ if (detailsProto.issueDate !== undefined) cd.issueDate = detailsProto.issueDate
+ if (detailsProto.nextOptionDate !== undefined) cd.nextOptionDate = detailsProto.nextOptionDate
+ if (detailsProto.nextOptionType !== undefined) cd.nextOptionType = detailsProto.nextOptionType
+ if (detailsProto.nextOptionPartial !== undefined) cd.nextOptionPartial = detailsProto.nextOptionPartial
+ if (detailsProto.bondNotes !== undefined) cd.notes = detailsProto.bondNotes
+
+ // Fund fields
+ if (detailsProto.fundName !== undefined) cd.fundName = detailsProto.fundName
+ if (detailsProto.fundFamily !== undefined) cd.fundFamily = detailsProto.fundFamily
+ if (detailsProto.fundType !== undefined) cd.fundType = detailsProto.fundType
+ if (detailsProto.fundFrontLoad !== undefined) cd.fundFrontLoad = detailsProto.fundFrontLoad
+ if (detailsProto.fundBackLoad !== undefined) cd.fundBackLoad = detailsProto.fundBackLoad
+ if (detailsProto.fundBackLoadTimeInterval !== undefined) cd.fundBackLoadTimeInterval = detailsProto.fundBackLoadTimeInterval
+ if (detailsProto.fundManagementFee !== undefined) cd.fundManagementFee = detailsProto.fundManagementFee
+ if (detailsProto.fundClosed !== undefined) cd.fundClosed = detailsProto.fundClosed
+ if (detailsProto.fundClosedForNewInvestors !== undefined) cd.fundClosedForNewInvestors = detailsProto.fundClosedForNewInvestors
+ if (detailsProto.fundClosedForNewMoney !== undefined) cd.fundClosedForNewMoney = detailsProto.fundClosedForNewMoney
+ if (detailsProto.fundNotifyAmount !== undefined) cd.fundNotifyAmount = detailsProto.fundNotifyAmount
+ if (detailsProto.fundMinimumInitialPurchase !== undefined) cd.fundMinimumInitialPurchase = detailsProto.fundMinimumInitialPurchase
+ if (detailsProto.fundMinimumSubsequentPurchase !== undefined) cd.fundSubsequentMinimumPurchase = detailsProto.fundMinimumSubsequentPurchase
+ if (detailsProto.fundBlueSkyStates !== undefined) cd.fundBlueSkyStates = detailsProto.fundBlueSkyStates
+ if (detailsProto.fundBlueSkyTerritories !== undefined) cd.fundBlueSkyTerritories = detailsProto.fundBlueSkyTerritories
+
+ if (detailsProto.fundDistributionPolicyIndicator !== undefined) {
+ cd.fundDistributionPolicyIndicator = getEnumTypeFromString(
+ FundDistributionPolicyIndicator, detailsProto.fundDistributionPolicyIndicator,
+ ) as typeof cd.fundDistributionPolicyIndicator
+ }
+ if (detailsProto.fundAssetType !== undefined) {
+ cd.fundAssetType = getEnumTypeFromString(
+ FundAssetType, detailsProto.fundAssetType,
+ ) as typeof cd.fundAssetType
+ }
+
+ // Ineligibility reasons
+ if (detailsProto.ineligibilityReasonList && detailsProto.ineligibilityReasonList.length > 0) {
+ cd.ineligibilityReasonList = detailsProto.ineligibilityReasonList.map((rp) => {
+ return new IneligibilityReason(rp.id, rp.description)
+ })
+ }
+
+ // Event contract fields
+ if (detailsProto.eventContract1 !== undefined) cd.eventContract1 = detailsProto.eventContract1
+ if (detailsProto.eventContractDescription1 !== undefined) cd.eventContractDescription1 = detailsProto.eventContractDescription1
+ if (detailsProto.eventContractDescription2 !== undefined) cd.eventContractDescription2 = detailsProto.eventContractDescription2
+
+ return cd
+}
+
+// ---------------------------------------------------------------------------
+// Text handlers
+// ---------------------------------------------------------------------------
+
+function processContractDataMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ let version = 8
+ if (d.serverVersion < MIN_SERVER_VER_SIZE_RULES) {
+ version = decodeInt(fields)
+ }
+
+ let reqId = -1
+ if (version >= 3) {
+ reqId = decodeInt(fields)
+ }
+
+ const contract = new ContractDetails()
+ contract.contract.symbol = decodeStr(fields)
+ contract.contract.secType = decodeStr(fields)
+ readLastTradeDate(fields, contract, false)
+ if (d.serverVersion >= MIN_SERVER_VER_LAST_TRADE_DATE) {
+ contract.contract.lastTradeDate = decodeStr(fields)
+ }
+ contract.contract.strike = decodeFloat(fields)
+ contract.contract.right = decodeStr(fields)
+ contract.contract.exchange = decodeStr(fields)
+ contract.contract.currency = decodeStr(fields)
+ contract.contract.localSymbol = decodeStr(fields)
+ contract.marketName = decodeStr(fields)
+ contract.contract.tradingClass = decodeStr(fields)
+ contract.contract.conId = decodeInt(fields)
+ contract.minTick = decodeFloat(fields)
+ if (
+ d.serverVersion >= MIN_SERVER_VER_MD_SIZE_MULTIPLIER &&
+ d.serverVersion < MIN_SERVER_VER_SIZE_RULES
+ ) {
+ decodeInt(fields) // mdSizeMultiplier - not used anymore
+ }
+ contract.contract.multiplier = decodeStr(fields)
+ contract.orderTypes = decodeStr(fields)
+ contract.validExchanges = decodeStr(fields)
+ contract.priceMagnifier = decodeInt(fields) // ver 2
+ if (version >= 4) {
+ contract.underConId = decodeInt(fields)
+ }
+ if (version >= 5) {
+ contract.longName =
+ d.serverVersion >= MIN_SERVER_VER_ENCODE_MSG_ASCII7
+ ? decodeStr(fields) // Python does unicode-escape; we just read the string
+ : decodeStr(fields)
+ contract.contract.primaryExchange = decodeStr(fields)
+ }
+ if (version >= 6) {
+ contract.contractMonth = decodeStr(fields)
+ contract.industry = decodeStr(fields)
+ contract.category = decodeStr(fields)
+ contract.subcategory = decodeStr(fields)
+ contract.timeZoneId = decodeStr(fields)
+ contract.tradingHours = decodeStr(fields)
+ contract.liquidHours = decodeStr(fields)
+ }
+ if (version >= 8) {
+ contract.evRule = decodeStr(fields)
+ contract.evMultiplier = decodeInt(fields)
+ }
+ if (version >= 7) {
+ const secIdListCount = decodeInt(fields)
+ if (secIdListCount > 0) {
+ contract.secIdList = []
+ for (let i = 0; i < secIdListCount; i++) {
+ const tagValue = new TagValue()
+ tagValue.tag = decodeStr(fields)
+ tagValue.value = decodeStr(fields)
+ contract.secIdList.push(tagValue)
+ }
+ }
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_AGG_GROUP) {
+ contract.aggGroup = decodeInt(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_UNDERLYING_INFO) {
+ contract.underSymbol = decodeStr(fields)
+ contract.underSecType = decodeStr(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_MARKET_RULES) {
+ contract.marketRuleIds = decodeStr(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_REAL_EXPIRATION_DATE) {
+ contract.realExpirationDate = decodeStr(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_STOCK_TYPE) {
+ contract.stockType = decodeStr(fields)
+ }
+
+ if (
+ d.serverVersion >= MIN_SERVER_VER_FRACTIONAL_SIZE_SUPPORT &&
+ d.serverVersion < MIN_SERVER_VER_SIZE_RULES
+ ) {
+ decodeDecimal(fields) // sizeMinTick - not used anymore
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_SIZE_RULES) {
+ contract.minSize = decodeDecimal(fields)
+ contract.sizeIncrement = decodeDecimal(fields)
+ contract.suggestedSizeIncrement = decodeDecimal(fields)
+ }
+
+ if (
+ d.serverVersion >= MIN_SERVER_VER_FUND_DATA_FIELDS &&
+ contract.contract.secType === 'FUND'
+ ) {
+ contract.fundName = decodeStr(fields)
+ contract.fundFamily = decodeStr(fields)
+ contract.fundType = decodeStr(fields)
+ contract.fundFrontLoad = decodeStr(fields)
+ contract.fundBackLoad = decodeStr(fields)
+ contract.fundBackLoadTimeInterval = decodeStr(fields)
+ contract.fundManagementFee = decodeStr(fields)
+ contract.fundClosed = decodeBool(fields)
+ contract.fundClosedForNewInvestors = decodeBool(fields)
+ contract.fundClosedForNewMoney = decodeBool(fields)
+ contract.fundNotifyAmount = decodeStr(fields)
+ contract.fundMinimumInitialPurchase = decodeStr(fields)
+ contract.fundSubsequentMinimumPurchase = decodeStr(fields)
+ contract.fundBlueSkyStates = decodeStr(fields)
+ contract.fundBlueSkyTerritories = decodeStr(fields)
+ contract.fundDistributionPolicyIndicator = getEnumTypeFromString(
+ FundDistributionPolicyIndicator, decodeStr(fields),
+ ) as typeof contract.fundDistributionPolicyIndicator
+ contract.fundAssetType = getEnumTypeFromString(
+ FundAssetType, decodeStr(fields),
+ ) as typeof contract.fundAssetType
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_INELIGIBILITY_REASONS) {
+ const ineligibilityReasonListCount = decodeInt(fields)
+ if (ineligibilityReasonListCount > 0) {
+ contract.ineligibilityReasonList = []
+ for (let i = 0; i < ineligibilityReasonListCount; i++) {
+ const reason = new IneligibilityReason()
+ reason.id = decodeStr(fields)
+ reason.description = decodeStr(fields)
+ contract.ineligibilityReasonList.push(reason)
+ }
+ }
+ }
+
+ d.wrapper.contractDetails(reqId, contract)
+}
+
+function processBondContractDataMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ let version = 6
+ if (d.serverVersion < MIN_SERVER_VER_SIZE_RULES) {
+ version = decodeInt(fields)
+ }
+
+ let reqId = -1
+ if (version >= 3) {
+ reqId = decodeInt(fields)
+ }
+
+ const contract = new ContractDetails()
+ contract.contract.symbol = decodeStr(fields)
+ contract.contract.secType = decodeStr(fields)
+ contract.cusip = decodeStr(fields)
+ contract.coupon = decodeFloat(fields)
+ readLastTradeDate(fields, contract, true)
+ contract.issueDate = decodeStr(fields)
+ contract.ratings = decodeStr(fields)
+ contract.bondType = decodeStr(fields)
+ contract.couponType = decodeStr(fields)
+ contract.convertible = decodeBool(fields)
+ contract.callable = decodeBool(fields)
+ contract.putable = decodeBool(fields)
+ contract.descAppend = decodeStr(fields)
+ contract.contract.exchange = decodeStr(fields)
+ contract.contract.currency = decodeStr(fields)
+ contract.marketName = decodeStr(fields)
+ contract.contract.tradingClass = decodeStr(fields)
+ contract.contract.conId = decodeInt(fields)
+ contract.minTick = decodeFloat(fields)
+ if (
+ d.serverVersion >= MIN_SERVER_VER_MD_SIZE_MULTIPLIER &&
+ d.serverVersion < MIN_SERVER_VER_SIZE_RULES
+ ) {
+ decodeInt(fields) // mdSizeMultiplier - not used anymore
+ }
+ contract.orderTypes = decodeStr(fields)
+ contract.validExchanges = decodeStr(fields)
+ contract.nextOptionDate = decodeStr(fields) // ver 2
+ contract.nextOptionType = decodeStr(fields) // ver 2
+ contract.nextOptionPartial = decodeBool(fields) // ver 2
+ contract.notes = decodeStr(fields) // ver 2
+ if (version >= 4) {
+ contract.longName = decodeStr(fields)
+ }
+ if (d.serverVersion >= MIN_SERVER_VER_BOND_TRADING_HOURS) {
+ contract.timeZoneId = decodeStr(fields)
+ contract.tradingHours = decodeStr(fields)
+ contract.liquidHours = decodeStr(fields)
+ }
+ if (version >= 6) {
+ contract.evRule = decodeStr(fields)
+ contract.evMultiplier = decodeInt(fields)
+ }
+ if (version >= 5) {
+ const secIdListCount = decodeInt(fields)
+ if (secIdListCount > 0) {
+ contract.secIdList = []
+ for (let i = 0; i < secIdListCount; i++) {
+ const tagValue = new TagValue()
+ tagValue.tag = decodeStr(fields)
+ tagValue.value = decodeStr(fields)
+ contract.secIdList.push(tagValue)
+ }
+ }
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_AGG_GROUP) {
+ contract.aggGroup = decodeInt(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_MARKET_RULES) {
+ contract.marketRuleIds = decodeStr(fields)
+ }
+
+ if (d.serverVersion >= MIN_SERVER_VER_SIZE_RULES) {
+ contract.minSize = decodeDecimal(fields)
+ contract.sizeIncrement = decodeDecimal(fields)
+ contract.suggestedSizeIncrement = decodeDecimal(fields)
+ }
+
+ d.wrapper.bondContractDetails(reqId, contract)
+}
+
+function processContractDataEndMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ d.wrapper.contractDetailsEnd(reqId)
+}
+
+function processSymbolSamplesMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const nContractDescriptions = decodeInt(fields)
+ const contractDescriptions: ContractDescription[] = []
+ for (let i = 0; i < nContractDescriptions; i++) {
+ const conDesc = new ContractDescription()
+ conDesc.contract.conId = decodeInt(fields)
+ conDesc.contract.symbol = decodeStr(fields)
+ conDesc.contract.secType = decodeStr(fields)
+ conDesc.contract.primaryExchange = decodeStr(fields)
+ conDesc.contract.currency = decodeStr(fields)
+
+ const nDerivativeSecTypes = decodeInt(fields)
+ conDesc.derivativeSecTypes = []
+ for (let j = 0; j < nDerivativeSecTypes; j++) {
+ conDesc.derivativeSecTypes.push(decodeStr(fields))
+ }
+ contractDescriptions.push(conDesc)
+
+ if (d.serverVersion >= MIN_SERVER_VER_BOND_ISSUERID) {
+ conDesc.contract.description = decodeStr(fields)
+ conDesc.contract.issuerId = decodeStr(fields)
+ }
+ }
+
+ d.wrapper.symbolSamples(reqId, contractDescriptions)
+}
+
+function processDeltaNeutralValidationMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+
+ const deltaNeutralContract = new DeltaNeutralContract()
+ deltaNeutralContract.conId = decodeInt(fields)
+ deltaNeutralContract.delta = decodeFloat(fields)
+ deltaNeutralContract.price = decodeFloat(fields)
+
+ d.wrapper.deltaNeutralValidation(reqId, deltaNeutralContract)
+}
+
+function processMarketRuleMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const marketRuleId = decodeInt(fields)
+
+ const nPriceIncrements = decodeInt(fields)
+ const priceIncrements: PriceIncrement[] = []
+
+ if (nPriceIncrements > 0) {
+ for (let i = 0; i < nPriceIncrements; i++) {
+ const prcInc = new PriceIncrement()
+ prcInc.lowEdge = decodeFloat(fields)
+ prcInc.increment = decodeFloat(fields)
+ priceIncrements.push(prcInc)
+ }
+ }
+
+ d.wrapper.marketRule(marketRuleId, priceIncrements)
+}
+
+// ---------------------------------------------------------------------------
+// Protobuf handlers
+// ---------------------------------------------------------------------------
+
+function processContractDataMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = ContractDataProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ if (proto.contract === undefined || proto.contractDetails === undefined) {
+ return
+ }
+ const contractDetails = decodeContractDetailsFromProto(proto.contract, proto.contractDetails, false)
+
+ d.wrapper.contractDetails(reqId, contractDetails)
+}
+
+function processBondContractDataMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = ContractDataProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ if (proto.contract === undefined || proto.contractDetails === undefined) {
+ return
+ }
+ const contractDetails = decodeContractDetailsFromProto(proto.contract, proto.contractDetails, true)
+
+ d.wrapper.bondContractDetails(reqId, contractDetails)
+}
+
+function processContractDataEndMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = ContractDataEndProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ d.wrapper.contractDetailsEnd(reqId)
+}
+
+function processSymbolSamplesMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = SymbolSamplesProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ const contractDescriptions: ContractDescription[] = []
+ if (proto.contractDescriptions) {
+ for (const cdProto of proto.contractDescriptions) {
+ const conDesc = new ContractDescription()
+ if (cdProto.contract !== undefined) {
+ conDesc.contract = decodeContractFromProto(cdProto.contract)
+ }
+ conDesc.derivativeSecTypes = cdProto.derivativeSecTypes ? [...cdProto.derivativeSecTypes] : []
+ contractDescriptions.push(conDesc)
+ }
+ }
+
+ d.wrapper.symbolSamples(reqId, contractDescriptions)
+}
+
+function processMarketRuleMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = MarketRuleProto.decode(buf)
+
+ const marketRuleId = proto.marketRuleId ?? 0
+
+ const priceIncrements: PriceIncrement[] = []
+ if (proto.priceIncrements) {
+ for (const pip of proto.priceIncrements) {
+ const pi = new PriceIncrement()
+ if (pip.lowEdge !== undefined) pi.lowEdge = pip.lowEdge
+ if (pip.increment !== undefined) pi.increment = pip.increment
+ priceIncrements.push(pi)
+ }
+ }
+
+ d.wrapper.marketRule(marketRuleId, priceIncrements)
+}
+
+// ---------------------------------------------------------------------------
+// Registration
+// ---------------------------------------------------------------------------
+
+export function applyContractHandlers(decoder: Decoder): void {
+ // Text handlers
+ decoder.registerText(IN.CONTRACT_DATA, processContractDataMsg)
+ decoder.registerText(IN.BOND_CONTRACT_DATA, processBondContractDataMsg)
+ decoder.registerText(IN.CONTRACT_DATA_END, processContractDataEndMsg)
+ decoder.registerText(IN.SYMBOL_SAMPLES, processSymbolSamplesMsg)
+ decoder.registerText(IN.DELTA_NEUTRAL_VALIDATION, processDeltaNeutralValidationMsg)
+ decoder.registerText(IN.MARKET_RULE, processMarketRuleMsg)
+
+ // Protobuf handlers
+ decoder.registerProto(IN.CONTRACT_DATA, processContractDataMsgProtoBuf)
+ decoder.registerProto(IN.BOND_CONTRACT_DATA, processBondContractDataMsgProtoBuf)
+ decoder.registerProto(IN.CONTRACT_DATA_END, processContractDataEndMsgProtoBuf)
+ decoder.registerProto(IN.SYMBOL_SAMPLES, processSymbolSamplesMsgProtoBuf)
+ decoder.registerProto(IN.MARKET_RULE, processMarketRuleMsgProtoBuf)
+}
diff --git a/packages/ibkr/src/decoder/execution.ts b/packages/ibkr/src/decoder/execution.ts
new file mode 100644
index 00000000..eb5dd10b
--- /dev/null
+++ b/packages/ibkr/src/decoder/execution.ts
@@ -0,0 +1,263 @@
+/**
+ * Execution-related decoder handlers (text + protobuf).
+ *
+ * Message types:
+ * IN.EXECUTION_DATA (11)
+ * IN.EXECUTION_DATA_END (55)
+ * IN.COMMISSION_AND_FEES_REPORT (59)
+ */
+
+import Decimal from 'decimal.js'
+import type { Decoder } from './base.js'
+import { IN } from '../message.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeBool,
+ decodeDecimal,
+} from '../utils.js'
+import {
+ MIN_SERVER_VER_LAST_LIQUIDITY,
+ MIN_SERVER_VER_MODELS_SUPPORT,
+ MIN_SERVER_VER_PENDING_PRICE_REVISION,
+ MIN_SERVER_VER_SUBMITTER,
+} from '../server-versions.js'
+import { NO_VALID_ID } from '../const.js'
+import { Contract, ComboLeg, DeltaNeutralContract } from '../contract.js'
+import { Execution, OptionExerciseType } from '../execution.js'
+import { CommissionAndFeesReport } from '../commission-and-fees-report.js'
+
+// Protobuf message types
+import { ExecutionDetails as ExecutionDetailsProto } from '../protobuf/ExecutionDetails.js'
+import { ExecutionDetailsEnd as ExecutionDetailsEndProto } from '../protobuf/ExecutionDetailsEnd.js'
+import { CommissionAndFeesReport as CommissionAndFeesReportProto } from '../protobuf/CommissionAndFeesReport.js'
+import type { Contract as ContractProtoType } from '../protobuf/Contract.js'
+import type { Execution as ExecutionProtoType } from '../protobuf/Execution.js'
+
+// ---------------------------------------------------------------------------
+// Protobuf → domain helpers
+// ---------------------------------------------------------------------------
+
+function decodeContractFromProto(cp: ContractProtoType): Contract {
+ const contract = new Contract()
+ if (cp.conId !== undefined) contract.conId = cp.conId
+ if (cp.symbol !== undefined) contract.symbol = cp.symbol
+ if (cp.secType !== undefined) contract.secType = cp.secType
+ if (cp.lastTradeDateOrContractMonth !== undefined) contract.lastTradeDateOrContractMonth = cp.lastTradeDateOrContractMonth
+ if (cp.strike !== undefined) contract.strike = cp.strike
+ if (cp.right !== undefined) contract.right = cp.right
+ if (cp.multiplier !== undefined) contract.multiplier = String(cp.multiplier)
+ if (cp.exchange !== undefined) contract.exchange = cp.exchange
+ if (cp.currency !== undefined) contract.currency = cp.currency
+ if (cp.localSymbol !== undefined) contract.localSymbol = cp.localSymbol
+ if (cp.tradingClass !== undefined) contract.tradingClass = cp.tradingClass
+ if (cp.comboLegsDescrip !== undefined) contract.comboLegsDescrip = cp.comboLegsDescrip
+
+ if (cp.comboLegs && cp.comboLegs.length > 0) {
+ contract.comboLegs = cp.comboLegs.map((clp) => {
+ const leg = new ComboLeg()
+ if (clp.conId !== undefined) leg.conId = clp.conId
+ if (clp.ratio !== undefined) leg.ratio = clp.ratio
+ if (clp.action !== undefined) leg.action = clp.action
+ if (clp.exchange !== undefined) leg.exchange = clp.exchange
+ if (clp.openClose !== undefined) leg.openClose = clp.openClose
+ if (clp.shortSalesSlot !== undefined) leg.shortSaleSlot = clp.shortSalesSlot
+ if (clp.designatedLocation !== undefined) leg.designatedLocation = clp.designatedLocation
+ if (clp.exemptCode !== undefined) leg.exemptCode = clp.exemptCode
+ return leg
+ })
+ }
+
+ if (cp.deltaNeutralContract !== undefined) {
+ const dnc = new DeltaNeutralContract()
+ if (cp.deltaNeutralContract.conId !== undefined) dnc.conId = cp.deltaNeutralContract.conId
+ if (cp.deltaNeutralContract.delta !== undefined) dnc.delta = cp.deltaNeutralContract.delta
+ if (cp.deltaNeutralContract.price !== undefined) dnc.price = cp.deltaNeutralContract.price
+ contract.deltaNeutralContract = dnc
+ }
+
+ if (cp.lastTradeDate !== undefined) contract.lastTradeDate = cp.lastTradeDate
+ if (cp.primaryExch !== undefined) contract.primaryExchange = cp.primaryExch
+ if (cp.issuerId !== undefined) contract.issuerId = cp.issuerId
+ if (cp.description !== undefined) contract.description = cp.description
+
+ return contract
+}
+
+function decodeExecutionFromProto(ep: ExecutionProtoType): Execution {
+ const execution = new Execution()
+ if (ep.orderId !== undefined) execution.orderId = ep.orderId
+ if (ep.clientId !== undefined) execution.clientId = ep.clientId
+ if (ep.execId !== undefined) execution.execId = ep.execId
+ if (ep.time !== undefined) execution.time = ep.time
+ if (ep.acctNumber !== undefined) execution.acctNumber = ep.acctNumber
+ if (ep.exchange !== undefined) execution.exchange = ep.exchange
+ if (ep.side !== undefined) execution.side = ep.side
+ if (ep.shares !== undefined) execution.shares = new Decimal(ep.shares)
+ if (ep.price !== undefined) execution.price = ep.price
+ if (ep.permId !== undefined) execution.permId = ep.permId
+ if (ep.isLiquidation !== undefined) execution.liquidation = ep.isLiquidation ? 1 : 0
+ if (ep.cumQty !== undefined) execution.cumQty = new Decimal(ep.cumQty)
+ if (ep.avgPrice !== undefined) execution.avgPrice = ep.avgPrice
+ if (ep.orderRef !== undefined) execution.orderRef = ep.orderRef
+ if (ep.evRule !== undefined) execution.evRule = ep.evRule
+ if (ep.evMultiplier !== undefined) execution.evMultiplier = ep.evMultiplier
+ if (ep.modelCode !== undefined) execution.modelCode = ep.modelCode
+ if (ep.lastLiquidity !== undefined) execution.lastLiquidity = ep.lastLiquidity
+ if (ep.isPriceRevisionPending !== undefined) execution.pendingPriceRevision = ep.isPriceRevisionPending
+ if (ep.submitter !== undefined) execution.submitter = ep.submitter
+ if (ep.optExerciseOrLapseType !== undefined) {
+ const entry = Object.values(OptionExerciseType).find((e) => e.value === ep.optExerciseOrLapseType)
+ if (entry) execution.optExerciseOrLapseType = entry
+ }
+ return execution
+}
+
+// ---------------------------------------------------------------------------
+// Public: register all execution handlers
+// ---------------------------------------------------------------------------
+
+export function applyExecutionHandlers(decoder: Decoder): void {
+ // ── Text handlers ──────────────────────────────────────────────────────
+
+ // IN.EXECUTION_DATA (11)
+ decoder.registerText(IN.EXECUTION_DATA, (d, fields) => {
+ decodeInt(fields) // msgId
+ let version = d.serverVersion
+
+ if (d.serverVersion < MIN_SERVER_VER_LAST_LIQUIDITY) {
+ version = decodeInt(fields)
+ }
+
+ let reqId = -1
+ if (version >= 7) {
+ reqId = decodeInt(fields)
+ }
+
+ const orderId = decodeInt(fields)
+
+ const contract = new Contract()
+ contract.conId = decodeInt(fields) // ver 5
+ contract.symbol = decodeStr(fields)
+ contract.secType = decodeStr(fields)
+ contract.lastTradeDateOrContractMonth = decodeStr(fields)
+ contract.strike = decodeFloat(fields)
+ contract.right = decodeStr(fields)
+ if (version >= 9) {
+ contract.multiplier = decodeStr(fields)
+ }
+ contract.exchange = decodeStr(fields)
+ contract.currency = decodeStr(fields)
+ contract.localSymbol = decodeStr(fields)
+ if (version >= 10) {
+ contract.tradingClass = decodeStr(fields)
+ }
+
+ const execution = new Execution()
+ execution.orderId = orderId
+ execution.execId = decodeStr(fields)
+ execution.time = decodeStr(fields)
+ execution.acctNumber = decodeStr(fields)
+ execution.exchange = decodeStr(fields)
+ execution.side = decodeStr(fields)
+ execution.shares = decodeDecimal(fields)
+ execution.price = decodeFloat(fields)
+ execution.permId = decodeInt(fields) // ver 2
+ execution.clientId = decodeInt(fields) // ver 3
+ execution.liquidation = decodeInt(fields) // ver 4
+
+ if (version >= 6) {
+ execution.cumQty = decodeDecimal(fields)
+ execution.avgPrice = decodeFloat(fields)
+ }
+
+ if (version >= 8) {
+ execution.orderRef = decodeStr(fields)
+ }
+
+ if (version >= 9) {
+ execution.evRule = decodeStr(fields)
+ execution.evMultiplier = decodeFloat(fields)
+ }
+ if (d.serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT) {
+ execution.modelCode = decodeStr(fields)
+ }
+ if (d.serverVersion >= MIN_SERVER_VER_LAST_LIQUIDITY) {
+ execution.lastLiquidity = decodeInt(fields)
+ }
+ if (d.serverVersion >= MIN_SERVER_VER_PENDING_PRICE_REVISION) {
+ execution.pendingPriceRevision = decodeBool(fields)
+ }
+ if (d.serverVersion >= MIN_SERVER_VER_SUBMITTER) {
+ execution.submitter = decodeStr(fields)
+ }
+
+ d.wrapper.execDetails(reqId, contract, execution)
+ })
+
+ // IN.EXECUTION_DATA_END (55)
+ decoder.registerText(IN.EXECUTION_DATA_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ d.wrapper.execDetailsEnd(reqId)
+ })
+
+ // IN.COMMISSION_AND_FEES_REPORT (59)
+ decoder.registerText(IN.COMMISSION_AND_FEES_REPORT, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+
+ const report = new CommissionAndFeesReport()
+ report.execId = decodeStr(fields)
+ report.commissionAndFees = decodeFloat(fields)
+ report.currency = decodeStr(fields)
+ report.realizedPNL = decodeFloat(fields)
+ report.yield_ = decodeFloat(fields)
+ report.yieldRedemptionDate = decodeInt(fields)
+
+ d.wrapper.commissionAndFeesReport(report)
+ })
+
+ // ── Protobuf handlers ─────────────────────────────────────────────────
+
+ // IN.EXECUTION_DATA (11) — protobuf
+ decoder.registerProto(IN.EXECUTION_DATA, (d, buf) => {
+ const proto = ExecutionDetailsProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ if (!proto.contract) return
+ const contract = decodeContractFromProto(proto.contract)
+
+ if (!proto.execution) return
+ const execution = decodeExecutionFromProto(proto.execution)
+
+ d.wrapper.execDetails(reqId, contract, execution)
+ })
+
+ // IN.EXECUTION_DATA_END (55) — protobuf
+ decoder.registerProto(IN.EXECUTION_DATA_END, (d, buf) => {
+ const proto = ExecutionDetailsEndProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ d.wrapper.execDetailsEnd(reqId)
+ })
+
+ // IN.COMMISSION_AND_FEES_REPORT (59) — protobuf
+ decoder.registerProto(IN.COMMISSION_AND_FEES_REPORT, (d, buf) => {
+ const proto = CommissionAndFeesReportProto.decode(buf)
+
+ const report = new CommissionAndFeesReport()
+ report.execId = proto.execId ?? ''
+ report.commissionAndFees = proto.commissionAndFees ?? 0.0
+ report.currency = proto.currency ?? ''
+ report.realizedPNL = proto.realizedPNL ?? 0.0
+ report.yield_ = proto.bondYield ?? 0.0
+ report.yieldRedemptionDate = proto.yieldRedemptionDate !== undefined
+ ? parseInt(proto.yieldRedemptionDate, 10)
+ : 0
+
+ d.wrapper.commissionAndFeesReport(report)
+ })
+}
diff --git a/packages/ibkr/src/decoder/historical.ts b/packages/ibkr/src/decoder/historical.ts
new file mode 100644
index 00000000..4e86edb2
--- /dev/null
+++ b/packages/ibkr/src/decoder/historical.ts
@@ -0,0 +1,586 @@
+/**
+ * Historical data decoder handlers — text + protobuf.
+ *
+ * Mirrors: ibapi/decoder.py (historical data, real-time bars, ticks, schedule)
+ */
+
+import Decimal from 'decimal.js'
+import type { Decoder } from './base.js'
+import { IN } from '../message.js'
+import { NO_VALID_ID, UNSET_DECIMAL } from '../const.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeBool,
+ decodeDecimal,
+} from '../utils.js'
+import {
+ MIN_SERVER_VER_SYNT_REALTIME_BARS,
+ MIN_SERVER_VER_HISTORICAL_DATA_END,
+} from '../server-versions.js'
+import {
+ BarData,
+ RealTimeBar,
+ HistogramData,
+ HistoricalTick,
+ HistoricalTickBidAsk,
+ HistoricalTickLast,
+ HistoricalSession,
+ TickAttribBidAsk,
+ TickAttribLast,
+} from '../common.js'
+// Protobuf message types
+import { HistoricalData as HistoricalDataProto } from '../protobuf/HistoricalData.js'
+import { HistoricalDataUpdate as HistoricalDataUpdateProto } from '../protobuf/HistoricalDataUpdate.js'
+import { HistoricalDataEnd as HistoricalDataEndProto } from '../protobuf/HistoricalDataEnd.js'
+import { RealTimeBarTick as RealTimeBarTickProto } from '../protobuf/RealTimeBarTick.js'
+import { HeadTimestamp as HeadTimestampProto } from '../protobuf/HeadTimestamp.js'
+import { HistogramData as HistogramDataProto } from '../protobuf/HistogramData.js'
+import { HistoricalTicks as HistoricalTicksProto } from '../protobuf/HistoricalTicks.js'
+import { HistoricalTicksBidAsk as HistoricalTicksBidAskProto } from '../protobuf/HistoricalTicksBidAsk.js'
+import { HistoricalTicksLast as HistoricalTicksLastProto } from '../protobuf/HistoricalTicksLast.js'
+import { TickByTickData as TickByTickDataProto } from '../protobuf/TickByTickData.js'
+import { HistoricalSchedule as HistoricalScheduleProto } from '../protobuf/HistoricalSchedule.js'
+import type { HistoricalDataBar } from '../protobuf/HistoricalDataBar.js'
+import type { HistogramDataEntry } from '../protobuf/HistogramDataEntry.js'
+import type { HistoricalTick as HistoricalTickProto } from '../protobuf/HistoricalTick.js'
+import type { HistoricalTickBidAsk as HistoricalTickBidAskProtoMsg } from '../protobuf/HistoricalTickBidAsk.js'
+import type { HistoricalTickLast as HistoricalTickLastProtoMsg } from '../protobuf/HistoricalTickLast.js'
+
+// ----------------------------------------------------------------
+// Proto → domain helpers
+// ----------------------------------------------------------------
+
+function decodeHistoricalDataBar(proto: HistoricalDataBar): BarData {
+ const bar = new BarData()
+ if (proto.date !== undefined) bar.date = proto.date
+ if (proto.open !== undefined) bar.open = proto.open
+ if (proto.high !== undefined) bar.high = proto.high
+ if (proto.low !== undefined) bar.low = proto.low
+ if (proto.close !== undefined) bar.close = proto.close
+ if (proto.volume !== undefined) bar.volume = new Decimal(proto.volume)
+ if (proto.WAP !== undefined) bar.wap = new Decimal(proto.WAP)
+ if (proto.barCount !== undefined) bar.barCount = proto.barCount
+ return bar
+}
+
+function decodeHistogramDataEntry(proto: HistogramDataEntry): HistogramData {
+ const hd = new HistogramData()
+ if (proto.price !== undefined) hd.price = proto.price
+ if (proto.size !== undefined) hd.size = new Decimal(proto.size)
+ return hd
+}
+
+function decodeHistoricalTickProto(proto: HistoricalTickProto): HistoricalTick {
+ const tick = new HistoricalTick()
+ if (proto.time !== undefined) tick.time = proto.time
+ if (proto.price !== undefined) tick.price = proto.price
+ if (proto.size !== undefined) tick.size = new Decimal(proto.size)
+ return tick
+}
+
+function decodeHistoricalTickBidAskProto(proto: HistoricalTickBidAskProtoMsg): HistoricalTickBidAsk {
+ const tick = new HistoricalTickBidAsk()
+ if (proto.time !== undefined) tick.time = proto.time
+
+ const attr = new TickAttribBidAsk()
+ if (proto.tickAttribBidAsk !== undefined) {
+ if (proto.tickAttribBidAsk.bidPastLow !== undefined) attr.bidPastLow = proto.tickAttribBidAsk.bidPastLow
+ if (proto.tickAttribBidAsk.askPastHigh !== undefined) attr.askPastHigh = proto.tickAttribBidAsk.askPastHigh
+ }
+ tick.tickAttribBidAsk = attr
+
+ if (proto.priceBid !== undefined) tick.priceBid = proto.priceBid
+ if (proto.priceAsk !== undefined) tick.priceAsk = proto.priceAsk
+ if (proto.sizeBid !== undefined) tick.sizeBid = new Decimal(proto.sizeBid)
+ if (proto.sizeAsk !== undefined) tick.sizeAsk = new Decimal(proto.sizeAsk)
+ return tick
+}
+
+function decodeHistoricalTickLastProto(proto: HistoricalTickLastProtoMsg): HistoricalTickLast {
+ const tick = new HistoricalTickLast()
+ if (proto.time !== undefined) tick.time = proto.time
+
+ const attr = new TickAttribLast()
+ if (proto.tickAttribLast !== undefined) {
+ if (proto.tickAttribLast.pastLimit !== undefined) attr.pastLimit = proto.tickAttribLast.pastLimit
+ if (proto.tickAttribLast.unreported !== undefined) attr.unreported = proto.tickAttribLast.unreported
+ }
+ tick.tickAttribLast = attr
+
+ if (proto.price !== undefined) tick.price = proto.price
+ if (proto.size !== undefined) tick.size = new Decimal(proto.size)
+ if (proto.exchange !== undefined) tick.exchange = proto.exchange
+ if (proto.specialConditions !== undefined) tick.specialConditions = proto.specialConditions
+ return tick
+}
+
+// ----------------------------------------------------------------
+// Text handlers
+// ----------------------------------------------------------------
+
+function processHistoricalDataMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ if (d.serverVersion < MIN_SERVER_VER_SYNT_REALTIME_BARS) {
+ decodeInt(fields) // version
+ }
+
+ const reqId = decodeInt(fields)
+
+ let startDateStr = ''
+ let endDateStr = ''
+ if (d.serverVersion < MIN_SERVER_VER_HISTORICAL_DATA_END) {
+ startDateStr = decodeStr(fields) // ver 2
+ endDateStr = decodeStr(fields) // ver 2
+ }
+
+ const itemCount = decodeInt(fields)
+
+ for (let i = 0; i < itemCount; i++) {
+ const bar = new BarData()
+ bar.date = decodeStr(fields)
+ bar.open = decodeFloat(fields)
+ bar.high = decodeFloat(fields)
+ bar.low = decodeFloat(fields)
+ bar.close = decodeFloat(fields)
+ bar.volume = decodeDecimal(fields)
+ bar.wap = decodeDecimal(fields)
+
+ if (d.serverVersion < MIN_SERVER_VER_SYNT_REALTIME_BARS) {
+ decodeStr(fields) // hasGaps
+ }
+
+ bar.barCount = decodeInt(fields) // ver 3
+
+ d.wrapper.historicalData(reqId, bar)
+ }
+
+ if (d.serverVersion < MIN_SERVER_VER_HISTORICAL_DATA_END) {
+ d.wrapper.historicalDataEnd(reqId, startDateStr, endDateStr)
+ }
+}
+
+function processHistoricalDataEndMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const startDateStr = decodeStr(fields)
+ const endDateStr = decodeStr(fields)
+
+ d.wrapper.historicalDataEnd(reqId, startDateStr, endDateStr)
+}
+
+function processHistoricalDataUpdateMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const bar = new BarData()
+ bar.barCount = decodeInt(fields)
+ bar.date = decodeStr(fields)
+ bar.open = decodeFloat(fields)
+ bar.close = decodeFloat(fields)
+ bar.high = decodeFloat(fields)
+ bar.low = decodeFloat(fields)
+ bar.wap = decodeDecimal(fields)
+ bar.volume = decodeDecimal(fields)
+ d.wrapper.historicalDataUpdate(reqId, bar)
+}
+
+function processRealTimeBarMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+
+ const bar = new RealTimeBar()
+ bar.time = decodeInt(fields)
+ bar.open_ = decodeFloat(fields)
+ bar.high = decodeFloat(fields)
+ bar.low = decodeFloat(fields)
+ bar.close = decodeFloat(fields)
+ bar.volume = decodeDecimal(fields)
+ bar.wap = decodeDecimal(fields)
+ bar.count = decodeInt(fields)
+
+ d.wrapper.realtimeBar(
+ reqId, bar.time, bar.open_, bar.high, bar.low, bar.close,
+ bar.volume, bar.wap, bar.count,
+ )
+}
+
+function processHeadTimestamp(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const headTimestamp = decodeStr(fields)
+ d.wrapper.headTimestamp(reqId, headTimestamp)
+}
+
+function processHistogramData(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const numPoints = decodeInt(fields)
+
+ const histogram: HistogramData[] = []
+ for (let i = 0; i < numPoints; i++) {
+ const dataPoint = new HistogramData()
+ dataPoint.price = decodeFloat(fields)
+ dataPoint.size = decodeDecimal(fields)
+ histogram.push(dataPoint)
+ }
+
+ d.wrapper.histogramData(reqId, histogram)
+}
+
+function processHistoricalTicks(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const tickCount = decodeInt(fields)
+
+ const ticks: HistoricalTick[] = []
+
+ for (let i = 0; i < tickCount; i++) {
+ const historicalTick = new HistoricalTick()
+ historicalTick.time = decodeInt(fields)
+ fields.next() // skip for consistency
+ historicalTick.price = decodeFloat(fields)
+ historicalTick.size = decodeDecimal(fields)
+ ticks.push(historicalTick)
+ }
+
+ const done = decodeBool(fields)
+
+ d.wrapper.historicalTicks(reqId, ticks, done)
+}
+
+function processHistoricalTicksBidAsk(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const tickCount = decodeInt(fields)
+
+ const ticks: HistoricalTickBidAsk[] = []
+
+ for (let i = 0; i < tickCount; i++) {
+ const historicalTickBidAsk = new HistoricalTickBidAsk()
+ historicalTickBidAsk.time = decodeInt(fields)
+ const mask = decodeInt(fields)
+ const tickAttribBidAsk = new TickAttribBidAsk()
+ tickAttribBidAsk.askPastHigh = (mask & 1) !== 0
+ tickAttribBidAsk.bidPastLow = (mask & 2) !== 0
+ historicalTickBidAsk.tickAttribBidAsk = tickAttribBidAsk
+ historicalTickBidAsk.priceBid = decodeFloat(fields)
+ historicalTickBidAsk.priceAsk = decodeFloat(fields)
+ historicalTickBidAsk.sizeBid = decodeDecimal(fields)
+ historicalTickBidAsk.sizeAsk = decodeDecimal(fields)
+ ticks.push(historicalTickBidAsk)
+ }
+
+ const done = decodeBool(fields)
+
+ d.wrapper.historicalTicksBidAsk(reqId, ticks, done)
+}
+
+function processHistoricalTicksLast(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const tickCount = decodeInt(fields)
+
+ const ticks: HistoricalTickLast[] = []
+
+ for (let i = 0; i < tickCount; i++) {
+ const historicalTickLast = new HistoricalTickLast()
+ historicalTickLast.time = decodeInt(fields)
+ const mask = decodeInt(fields)
+ const tickAttribLast = new TickAttribLast()
+ tickAttribLast.pastLimit = (mask & 1) !== 0
+ tickAttribLast.unreported = (mask & 2) !== 0
+ historicalTickLast.tickAttribLast = tickAttribLast
+ historicalTickLast.price = decodeFloat(fields)
+ historicalTickLast.size = decodeDecimal(fields)
+ historicalTickLast.exchange = decodeStr(fields)
+ historicalTickLast.specialConditions = decodeStr(fields)
+ ticks.push(historicalTickLast)
+ }
+
+ const done = decodeBool(fields)
+
+ d.wrapper.historicalTicksLast(reqId, ticks, done)
+}
+
+function processTickByTickMsg(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const tickType = decodeInt(fields)
+ const time = decodeInt(fields)
+
+ if (tickType === 0) {
+ // None
+ } else if (tickType === 1 || tickType === 2) {
+ // Last or AllLast
+ const price = decodeFloat(fields)
+ const size = decodeDecimal(fields)
+ const mask = decodeInt(fields)
+
+ const tickAttribLast = new TickAttribLast()
+ tickAttribLast.pastLimit = (mask & 1) !== 0
+ tickAttribLast.unreported = (mask & 2) !== 0
+ const exchange = decodeStr(fields)
+ const specialConditions = decodeStr(fields)
+
+ d.wrapper.tickByTickAllLast(
+ reqId, tickType, time, price, size,
+ tickAttribLast, exchange, specialConditions,
+ )
+ } else if (tickType === 3) {
+ // BidAsk
+ const bidPrice = decodeFloat(fields)
+ const askPrice = decodeFloat(fields)
+ const bidSize = decodeDecimal(fields)
+ const askSize = decodeDecimal(fields)
+ const mask = decodeInt(fields)
+ const tickAttribBidAsk = new TickAttribBidAsk()
+ tickAttribBidAsk.bidPastLow = (mask & 1) !== 0
+ tickAttribBidAsk.askPastHigh = (mask & 2) !== 0
+
+ d.wrapper.tickByTickBidAsk(
+ reqId, time, bidPrice, askPrice, bidSize, askSize, tickAttribBidAsk,
+ )
+ } else if (tickType === 4) {
+ // MidPoint
+ const midPoint = decodeFloat(fields)
+ d.wrapper.tickByTickMidPoint(reqId, time, midPoint)
+ }
+}
+
+function processHistoricalSchedule(d: Decoder, fields: Iterator): void {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const startDateTime = decodeStr(fields)
+ const endDateTime = decodeStr(fields)
+ const timeZone = decodeStr(fields)
+ const sessionsCount = decodeInt(fields)
+
+ const sessions: HistoricalSession[] = []
+
+ for (let i = 0; i < sessionsCount; i++) {
+ const historicalSession = new HistoricalSession()
+ historicalSession.startDateTime = decodeStr(fields)
+ historicalSession.endDateTime = decodeStr(fields)
+ historicalSession.refDate = decodeStr(fields)
+ sessions.push(historicalSession)
+ }
+
+ d.wrapper.historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions)
+}
+
+// ----------------------------------------------------------------
+// Protobuf handlers
+// ----------------------------------------------------------------
+
+function processHistoricalDataMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalDataProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ if (!proto.historicalDataBars || proto.historicalDataBars.length === 0) return
+
+ for (const barProto of proto.historicalDataBars) {
+ const bar = decodeHistoricalDataBar(barProto)
+ d.wrapper.historicalData(reqId, bar)
+ }
+}
+
+function processHistoricalDataEndMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalDataEndProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const startDateStr = proto.startDateStr ?? ''
+ const endDateStr = proto.endDateStr ?? ''
+
+ d.wrapper.historicalDataEnd(reqId, startDateStr, endDateStr)
+}
+
+function processHistoricalDataUpdateMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalDataUpdateProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ if (proto.historicalDataBar === undefined) return
+
+ const bar = decodeHistoricalDataBar(proto.historicalDataBar)
+ d.wrapper.historicalDataUpdate(reqId, bar)
+}
+
+function processRealTimeBarMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = RealTimeBarTickProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const time = proto.time ?? 0
+ const open_ = proto.open ?? 0.0
+ const high = proto.high ?? 0.0
+ const low = proto.low ?? 0.0
+ const close = proto.close ?? 0.0
+ const volume = proto.volume !== undefined ? new Decimal(proto.volume) : UNSET_DECIMAL
+ const wap = proto.WAP !== undefined ? new Decimal(proto.WAP) : UNSET_DECIMAL
+ const count = proto.count ?? 0
+
+ d.wrapper.realtimeBar(reqId, time, open_, high, low, close, volume, wap, count)
+}
+
+function processHeadTimestampMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HeadTimestampProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const headTimestamp = proto.headTimestamp ?? ''
+
+ d.wrapper.headTimestamp(reqId, headTimestamp)
+}
+
+function processHistogramDataMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistogramDataProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ const histogram: HistogramData[] = []
+ if (proto.histogramDataEntries) {
+ for (const entry of proto.histogramDataEntries) {
+ histogram.push(decodeHistogramDataEntry(entry))
+ }
+ }
+
+ d.wrapper.histogramData(reqId, histogram)
+}
+
+function processHistoricalTicksMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalTicksProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const isDone = proto.isDone ?? false
+
+ const ticks: HistoricalTick[] = []
+ if (proto.historicalTicks) {
+ for (const tickProto of proto.historicalTicks) {
+ ticks.push(decodeHistoricalTickProto(tickProto))
+ }
+ }
+
+ d.wrapper.historicalTicks(reqId, ticks, isDone)
+}
+
+function processHistoricalTicksBidAskMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalTicksBidAskProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const isDone = proto.isDone ?? false
+
+ const ticks: HistoricalTickBidAsk[] = []
+ if (proto.historicalTicksBidAsk) {
+ for (const tickProto of proto.historicalTicksBidAsk) {
+ ticks.push(decodeHistoricalTickBidAskProto(tickProto))
+ }
+ }
+
+ d.wrapper.historicalTicksBidAsk(reqId, ticks, isDone)
+}
+
+function processHistoricalTicksLastMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalTicksLastProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const isDone = proto.isDone ?? false
+
+ const ticks: HistoricalTickLast[] = []
+ if (proto.historicalTicksLast) {
+ for (const tickProto of proto.historicalTicksLast) {
+ ticks.push(decodeHistoricalTickLastProto(tickProto))
+ }
+ }
+
+ d.wrapper.historicalTicksLast(reqId, ticks, isDone)
+}
+
+function processTickByTickMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = TickByTickDataProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tickType = proto.tickType ?? 0
+
+ if (tickType === 0) {
+ // None
+ } else if (tickType === 1 || tickType === 2) {
+ // Last or AllLast
+ if (proto.historicalTickLast !== undefined) {
+ const tick = decodeHistoricalTickLastProto(proto.historicalTickLast)
+ d.wrapper.tickByTickAllLast(
+ reqId, tickType, tick.time, tick.price, tick.size,
+ tick.tickAttribLast, tick.exchange, tick.specialConditions,
+ )
+ }
+ } else if (tickType === 3) {
+ // BidAsk
+ if (proto.historicalTickBidAsk !== undefined) {
+ const tick = decodeHistoricalTickBidAskProto(proto.historicalTickBidAsk)
+ d.wrapper.tickByTickBidAsk(
+ reqId, tick.time, tick.priceBid, tick.priceAsk,
+ tick.sizeBid, tick.sizeAsk, tick.tickAttribBidAsk,
+ )
+ }
+ } else if (tickType === 4) {
+ // MidPoint
+ if (proto.historicalTickMidPoint !== undefined) {
+ const tick = decodeHistoricalTickProto(proto.historicalTickMidPoint)
+ d.wrapper.tickByTickMidPoint(reqId, tick.time, tick.price)
+ }
+ }
+}
+
+function processHistoricalScheduleMsgProtoBuf(d: Decoder, buf: Buffer): void {
+ const proto = HistoricalScheduleProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const startDateTime = proto.startDateTime ?? ''
+ const endDateTime = proto.endDateTime ?? ''
+ const timeZone = proto.timeZone ?? ''
+
+ const sessions: HistoricalSession[] = []
+ if (proto.historicalSessions) {
+ for (const sessionProto of proto.historicalSessions) {
+ const session = new HistoricalSession()
+ session.startDateTime = sessionProto.startDateTime ?? ''
+ session.endDateTime = sessionProto.endDateTime ?? ''
+ session.refDate = sessionProto.refDate ?? ''
+ sessions.push(session)
+ }
+ }
+
+ d.wrapper.historicalSchedule(reqId, startDateTime, endDateTime, timeZone, sessions)
+}
+
+// ----------------------------------------------------------------
+// Registration
+// ----------------------------------------------------------------
+
+export function applyHistoricalHandlers(decoder: Decoder): void {
+ // Text handlers
+ decoder.registerText(IN.HISTORICAL_DATA, processHistoricalDataMsg)
+ decoder.registerText(IN.HISTORICAL_DATA_UPDATE, processHistoricalDataUpdateMsg)
+ decoder.registerText(IN.HISTORICAL_DATA_END, processHistoricalDataEndMsg)
+ decoder.registerText(IN.REAL_TIME_BARS, processRealTimeBarMsg)
+ decoder.registerText(IN.HEAD_TIMESTAMP, processHeadTimestamp)
+ decoder.registerText(IN.HISTOGRAM_DATA, processHistogramData)
+ decoder.registerText(IN.HISTORICAL_TICKS, processHistoricalTicks)
+ decoder.registerText(IN.HISTORICAL_TICKS_BID_ASK, processHistoricalTicksBidAsk)
+ decoder.registerText(IN.HISTORICAL_TICKS_LAST, processHistoricalTicksLast)
+ decoder.registerText(IN.TICK_BY_TICK, processTickByTickMsg)
+ decoder.registerText(IN.HISTORICAL_SCHEDULE, processHistoricalSchedule)
+
+ // Protobuf handlers
+ decoder.registerProto(IN.HISTORICAL_DATA, processHistoricalDataMsgProtoBuf)
+ decoder.registerProto(IN.HISTORICAL_DATA_UPDATE, processHistoricalDataUpdateMsgProtoBuf)
+ decoder.registerProto(IN.HISTORICAL_DATA_END, processHistoricalDataEndMsgProtoBuf)
+ decoder.registerProto(IN.REAL_TIME_BARS, processRealTimeBarMsgProtoBuf)
+ decoder.registerProto(IN.HEAD_TIMESTAMP, processHeadTimestampMsgProtoBuf)
+ decoder.registerProto(IN.HISTOGRAM_DATA, processHistogramDataMsgProtoBuf)
+ decoder.registerProto(IN.HISTORICAL_TICKS, processHistoricalTicksMsgProtoBuf)
+ decoder.registerProto(IN.HISTORICAL_TICKS_BID_ASK, processHistoricalTicksBidAskMsgProtoBuf)
+ decoder.registerProto(IN.HISTORICAL_TICKS_LAST, processHistoricalTicksLastMsgProtoBuf)
+ decoder.registerProto(IN.TICK_BY_TICK, processTickByTickMsgProtoBuf)
+ decoder.registerProto(IN.HISTORICAL_SCHEDULE, processHistoricalScheduleMsgProtoBuf)
+}
diff --git a/packages/ibkr/src/decoder/index.ts b/packages/ibkr/src/decoder/index.ts
new file mode 100644
index 00000000..4af8bfd0
--- /dev/null
+++ b/packages/ibkr/src/decoder/index.ts
@@ -0,0 +1,29 @@
+/**
+ * Decoder module — assembles base + all handler groups.
+ *
+ * Usage:
+ * import { Decoder, applyAllHandlers } from './decoder'
+ * const decoder = new Decoder(wrapper, serverVersion)
+ * 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'
+
+export function applyAllHandlers(decoder: Decoder): void {
+ applyMarketDataHandlers(decoder)
+ applyOrderHandlers(decoder)
+ applyAccountHandlers(decoder)
+ applyContractHandlers(decoder)
+ applyExecutionHandlers(decoder)
+ applyHistoricalHandlers(decoder)
+ applyMiscHandlers(decoder)
+}
+
+export { Decoder }
diff --git a/packages/ibkr/src/decoder/market-data.ts b/packages/ibkr/src/decoder/market-data.ts
new file mode 100644
index 00000000..16be6223
--- /dev/null
+++ b/packages/ibkr/src/decoder/market-data.ts
@@ -0,0 +1,469 @@
+/**
+ * Market data decoder handlers — text + protobuf.
+ * Mirrors market-data related processXxxMsg / processXxxMsgProtoBuf from ibapi/decoder.py
+ */
+
+import type { Decoder } from './base.js'
+import { IN } from '../message.js'
+import { NO_VALID_ID, UNSET_INTEGER, UNSET_DOUBLE, UNSET_DECIMAL } from '../const.js'
+import { decodeStr, decodeInt, decodeFloat, decodeBool, decodeDecimal } from '../utils.js'
+import {
+ MIN_SERVER_VER_PAST_LIMIT,
+ MIN_SERVER_VER_PRE_OPEN_BID_ASK,
+ MIN_SERVER_VER_SMART_DEPTH,
+ MIN_SERVER_VER_PRICE_BASED_VOLATILITY,
+} from '../server-versions.js'
+import { TickAttrib } from '../common.js'
+import { TickTypeEnum } from '../tick-type.js'
+import Decimal from 'decimal.js'
+
+// Proto imports
+import { TickPrice as TickPriceProto } from '../protobuf/TickPrice.js'
+import { TickSize as TickSizeProto } from '../protobuf/TickSize.js'
+import { TickOptionComputation as TickOptionComputationProto } from '../protobuf/TickOptionComputation.js'
+import { TickGeneric as TickGenericProto } from '../protobuf/TickGeneric.js'
+import { TickString as TickStringProto } from '../protobuf/TickString.js'
+import { TickSnapshotEnd as TickSnapshotEndProto } from '../protobuf/TickSnapshotEnd.js'
+import { MarketDataType as MarketDataTypeProto } from '../protobuf/MarketDataType.js'
+import { TickReqParams as TickReqParamsProto } from '../protobuf/TickReqParams.js'
+import { MarketDepth as MarketDepthProto } from '../protobuf/MarketDepth.js'
+import { MarketDepthL2 as MarketDepthL2Proto } from '../protobuf/MarketDepthL2.js'
+
+export function applyMarketDataHandlers(decoder: Decoder): void {
+ // ----------------------------------------------------------------
+ // Text handlers
+ // ----------------------------------------------------------------
+
+ // IN.TICK_PRICE (1)
+ decoder.registerText(IN.TICK_PRICE, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+
+ const reqId = decodeInt(fields)
+ const tickType = decodeInt(fields)
+ const price = decodeFloat(fields)
+ const size = decodeDecimal(fields) // ver 2 field
+ const attrMask = decodeInt(fields) // ver 3 field
+
+ const attrib = new TickAttrib()
+
+ attrib.canAutoExecute = attrMask === 1
+
+ if (d.serverVersion >= MIN_SERVER_VER_PAST_LIMIT) {
+ attrib.canAutoExecute = (attrMask & 1) !== 0
+ attrib.pastLimit = (attrMask & 2) !== 0
+ if (d.serverVersion >= MIN_SERVER_VER_PRE_OPEN_BID_ASK) {
+ attrib.preOpen = (attrMask & 4) !== 0
+ }
+ }
+
+ d.wrapper.tickPrice(reqId, tickType, price, attrib)
+
+ // process ver 2 fields
+ let sizeTickType: number = TickTypeEnum.NOT_SET
+ if (TickTypeEnum.BID === tickType) {
+ sizeTickType = TickTypeEnum.BID_SIZE
+ } else if (TickTypeEnum.ASK === tickType) {
+ sizeTickType = TickTypeEnum.ASK_SIZE
+ } else if (TickTypeEnum.LAST === tickType) {
+ sizeTickType = TickTypeEnum.LAST_SIZE
+ } else if (TickTypeEnum.DELAYED_BID === tickType) {
+ sizeTickType = TickTypeEnum.DELAYED_BID_SIZE
+ } else if (TickTypeEnum.DELAYED_ASK === tickType) {
+ sizeTickType = TickTypeEnum.DELAYED_ASK_SIZE
+ } else if (TickTypeEnum.DELAYED_LAST === tickType) {
+ sizeTickType = TickTypeEnum.DELAYED_LAST_SIZE
+ }
+
+ if (sizeTickType !== TickTypeEnum.NOT_SET) {
+ d.wrapper.tickSize(reqId, sizeTickType, size)
+ }
+ })
+
+ // IN.TICK_SIZE (2)
+ decoder.registerText(IN.TICK_SIZE, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+
+ const reqId = decodeInt(fields)
+ const sizeTickType = decodeInt(fields)
+ const size = decodeDecimal(fields)
+
+ if (sizeTickType !== TickTypeEnum.NOT_SET) {
+ d.wrapper.tickSize(reqId, sizeTickType, size)
+ }
+ })
+
+ // IN.TICK_OPTION_COMPUTATION (21)
+ decoder.registerText(IN.TICK_OPTION_COMPUTATION, (d, fields) => {
+ decodeInt(fields) // msgId
+ let version = d.serverVersion
+ let tickAttrib = 0
+ let optPrice: number | null = null
+ let pvDividend: number | null = null
+ let gamma: number | null = null
+ let vega: number | null = null
+ let theta: number | null = null
+ let undPrice: number | null = null
+
+ if (d.serverVersion < MIN_SERVER_VER_PRICE_BASED_VOLATILITY) {
+ version = decodeInt(fields)
+ }
+
+ const reqId = decodeInt(fields)
+ const tickTypeInt = decodeInt(fields)
+
+ if (d.serverVersion >= MIN_SERVER_VER_PRICE_BASED_VOLATILITY) {
+ tickAttrib = decodeInt(fields)
+ }
+
+ let impliedVol: number | null = decodeFloat(fields)
+ let delta: number | null = decodeFloat(fields)
+
+ if (impliedVol! < 0) impliedVol = null // -1 = not computed
+ if (delta === -2) delta = null // -2 = not computed
+
+ if (
+ version >= 6 ||
+ tickTypeInt === TickTypeEnum.MODEL_OPTION ||
+ tickTypeInt === TickTypeEnum.DELAYED_MODEL_OPTION
+ ) {
+ optPrice = decodeFloat(fields)
+ pvDividend = decodeFloat(fields)
+
+ if (optPrice === -1) optPrice = null
+ if (pvDividend === -1) pvDividend = null
+ }
+
+ if (version >= 6) {
+ gamma = decodeFloat(fields)
+ vega = decodeFloat(fields)
+ theta = decodeFloat(fields)
+ undPrice = decodeFloat(fields)
+
+ if (gamma === -2) gamma = null
+ if (vega === -2) vega = null
+ if (theta === -2) theta = null
+ if (undPrice === -1) undPrice = null
+ }
+
+ d.wrapper.tickOptionComputation(
+ reqId, tickTypeInt, tickAttrib,
+ impliedVol, delta, optPrice, pvDividend,
+ gamma, vega, theta, undPrice,
+ )
+ })
+
+ // IN.TICK_GENERIC (45)
+ decoder.registerText(IN.TICK_GENERIC, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const tickType = decodeInt(fields)
+ const value = decodeFloat(fields)
+ d.wrapper.tickGeneric(reqId, tickType, value)
+ })
+
+ // IN.TICK_STRING (46)
+ decoder.registerText(IN.TICK_STRING, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const tickType = decodeInt(fields)
+ const value = decodeStr(fields)
+ d.wrapper.tickString(reqId, tickType, value)
+ })
+
+ // IN.TICK_EFP (47) — text only, no proto
+ decoder.registerText(IN.TICK_EFP, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const tickType = decodeInt(fields)
+ const basisPoints = decodeFloat(fields)
+ const formattedBasisPoints = decodeStr(fields)
+ const impliedFuturesPrice = decodeFloat(fields)
+ const holdDays = decodeInt(fields)
+ const futureLastTradeDate = decodeStr(fields)
+ const dividendImpact = decodeFloat(fields)
+ const dividendsToLastTradeDate = decodeFloat(fields)
+ d.wrapper.tickEFP(
+ reqId, tickType, basisPoints, formattedBasisPoints,
+ impliedFuturesPrice, holdDays, futureLastTradeDate,
+ dividendImpact, dividendsToLastTradeDate,
+ )
+ })
+
+ // IN.TICK_SNAPSHOT_END (57)
+ decoder.registerText(IN.TICK_SNAPSHOT_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ d.wrapper.tickSnapshotEnd(reqId)
+ })
+
+ // IN.MARKET_DATA_TYPE (58)
+ decoder.registerText(IN.MARKET_DATA_TYPE, (d, fields) => {
+ decodeInt(fields) // msgId (version)
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const marketDataType = decodeInt(fields)
+ d.wrapper.marketDataType(reqId, marketDataType)
+ })
+
+ // IN.TICK_REQ_PARAMS (81)
+ decoder.registerText(IN.TICK_REQ_PARAMS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const tickerId = decodeInt(fields)
+ const minTick = decodeFloat(fields)
+ const bboExchange = decodeStr(fields)
+ const snapshotPermissions = decodeInt(fields)
+ d.wrapper.tickReqParams(tickerId, minTick, bboExchange, snapshotPermissions)
+ })
+
+ // IN.MARKET_DEPTH (12)
+ decoder.registerText(IN.MARKET_DEPTH, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+
+ const position = decodeInt(fields)
+ const operation = decodeInt(fields)
+ const side = decodeInt(fields)
+ const price = decodeFloat(fields)
+ const size = decodeDecimal(fields)
+
+ d.wrapper.updateMktDepth(reqId, position, operation, side, price, size)
+ })
+
+ // IN.MARKET_DEPTH_L2 (13)
+ decoder.registerText(IN.MARKET_DEPTH_L2, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+
+ const position = decodeInt(fields)
+ const marketMaker = decodeStr(fields)
+ const operation = decodeInt(fields)
+ const side = decodeInt(fields)
+ const price = decodeFloat(fields)
+ const size = decodeDecimal(fields)
+ let isSmartDepth = false
+
+ if (d.serverVersion >= MIN_SERVER_VER_SMART_DEPTH) {
+ isSmartDepth = decodeBool(fields)
+ }
+
+ d.wrapper.updateMktDepthL2(
+ reqId, position, marketMaker, operation, side, price, size, isSmartDepth,
+ )
+ })
+
+ // IN.REROUTE_MKT_DATA_REQ (91)
+ decoder.registerText(IN.REROUTE_MKT_DATA_REQ, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const conId = decodeInt(fields)
+ const exchange = decodeStr(fields)
+ d.wrapper.rerouteMktDataReq(reqId, conId, exchange)
+ })
+
+ // IN.REROUTE_MKT_DEPTH_REQ (92)
+ decoder.registerText(IN.REROUTE_MKT_DEPTH_REQ, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const conId = decodeInt(fields)
+ const exchange = decodeStr(fields)
+ d.wrapper.rerouteMktDepthReq(reqId, conId, exchange)
+ })
+
+ // ----------------------------------------------------------------
+ // Proto handlers
+ // ----------------------------------------------------------------
+
+ // IN.TICK_PRICE (1)
+ decoder.registerProto(IN.TICK_PRICE, (d, buf) => {
+ const proto = TickPriceProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tickType = proto.tickType ?? UNSET_INTEGER
+ const price = proto.price ?? UNSET_DOUBLE
+ const size = proto.size !== undefined ? new Decimal(proto.size) : UNSET_DECIMAL
+ const attrMask = proto.attrMask ?? UNSET_INTEGER
+
+ const attrib = new TickAttrib()
+ attrib.canAutoExecute = (attrMask & 1) !== 0
+ attrib.pastLimit = (attrMask & 2) !== 0
+ attrib.preOpen = (attrMask & 4) !== 0
+
+ d.wrapper.tickPrice(reqId, tickType, price, attrib)
+
+ let sizeTickType: number = TickTypeEnum.NOT_SET
+ if (TickTypeEnum.BID === tickType) {
+ sizeTickType = TickTypeEnum.BID_SIZE
+ } else if (TickTypeEnum.ASK === tickType) {
+ sizeTickType = TickTypeEnum.ASK_SIZE
+ } else if (TickTypeEnum.LAST === tickType) {
+ sizeTickType = TickTypeEnum.LAST_SIZE
+ } else if (TickTypeEnum.DELAYED_BID === tickType) {
+ sizeTickType = TickTypeEnum.DELAYED_BID_SIZE
+ } else if (TickTypeEnum.DELAYED_ASK === tickType) {
+ sizeTickType = TickTypeEnum.DELAYED_ASK_SIZE
+ } else if (TickTypeEnum.DELAYED_LAST === tickType) {
+ sizeTickType = TickTypeEnum.DELAYED_LAST_SIZE
+ }
+
+ if (sizeTickType !== TickTypeEnum.NOT_SET) {
+ d.wrapper.tickSize(reqId, sizeTickType, size)
+ }
+ })
+
+ // IN.TICK_SIZE (2)
+ decoder.registerProto(IN.TICK_SIZE, (d, buf) => {
+ const proto = TickSizeProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tickType = proto.tickType ?? UNSET_INTEGER
+ const size = proto.size !== undefined ? new Decimal(proto.size) : UNSET_DECIMAL
+
+ if (tickType !== TickTypeEnum.NOT_SET) {
+ d.wrapper.tickSize(reqId, tickType, size)
+ }
+ })
+
+ // IN.TICK_OPTION_COMPUTATION (21)
+ decoder.registerProto(IN.TICK_OPTION_COMPUTATION, (d, buf) => {
+ const proto = TickOptionComputationProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tickType = proto.tickType ?? UNSET_INTEGER
+ const tickAttrib = proto.tickAttrib ?? UNSET_INTEGER
+
+ let impliedVol: number | null = proto.impliedVol ?? null
+ if (impliedVol !== null && impliedVol < 0) impliedVol = null // -1 = not computed
+
+ let delta: number | null = proto.delta ?? null
+ if (delta !== null && delta === -2) delta = null // -2 = not computed
+
+ let optPrice: number | null = proto.optPrice ?? null
+ if (optPrice !== null && optPrice === -1) optPrice = null // -1 = not computed
+
+ let pvDividend: number | null = proto.pvDividend ?? null
+ if (pvDividend !== null && pvDividend === -1) pvDividend = null // -1 = not computed
+
+ let gamma: number | null = proto.gamma ?? null
+ if (gamma !== null && gamma === -2) gamma = null // -2 = not yet computed
+
+ let vega: number | null = proto.vega ?? null
+ if (vega !== null && vega === -2) vega = null // -2 = not yet computed
+
+ let theta: number | null = proto.theta ?? null
+ if (theta !== null && theta === -2) theta = null // -2 = not yet computed
+
+ let undPrice: number | null = proto.undPrice ?? null
+ if (undPrice !== null && undPrice === -1) undPrice = null // -1 = not computed
+
+ d.wrapper.tickOptionComputation(
+ reqId, tickType, tickAttrib,
+ impliedVol, delta, optPrice, pvDividend,
+ gamma, vega, theta, undPrice,
+ )
+ })
+
+ // IN.TICK_GENERIC (45)
+ decoder.registerProto(IN.TICK_GENERIC, (d, buf) => {
+ const proto = TickGenericProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tickType = proto.tickType ?? UNSET_INTEGER
+ const value = proto.value ?? UNSET_DOUBLE
+
+ if (tickType !== TickTypeEnum.NOT_SET) {
+ d.wrapper.tickGeneric(reqId, tickType, value)
+ }
+ })
+
+ // IN.TICK_STRING (46)
+ decoder.registerProto(IN.TICK_STRING, (d, buf) => {
+ const proto = TickStringProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tickType = proto.tickType ?? UNSET_INTEGER
+ const value = proto.value ?? ''
+
+ if (tickType !== TickTypeEnum.NOT_SET) {
+ d.wrapper.tickString(reqId, tickType, value)
+ }
+ })
+
+ // IN.TICK_SNAPSHOT_END (57)
+ decoder.registerProto(IN.TICK_SNAPSHOT_END, (d, buf) => {
+ const proto = TickSnapshotEndProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ d.wrapper.tickSnapshotEnd(reqId)
+ })
+
+ // IN.MARKET_DATA_TYPE (58)
+ decoder.registerProto(IN.MARKET_DATA_TYPE, (d, buf) => {
+ const proto = MarketDataTypeProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const marketDataType = proto.marketDataType ?? UNSET_INTEGER
+
+ d.wrapper.marketDataType(reqId, marketDataType)
+ })
+
+ // IN.TICK_REQ_PARAMS (81)
+ decoder.registerProto(IN.TICK_REQ_PARAMS, (d, buf) => {
+ const proto = TickReqParamsProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const minTick = proto.minTick !== undefined ? parseFloat(proto.minTick) : UNSET_DOUBLE
+ const bboExchange = proto.bboExchange ?? ''
+ const snapshotPermissions = proto.snapshotPermissions ?? UNSET_INTEGER
+
+ d.wrapper.tickReqParams(reqId, minTick, bboExchange, snapshotPermissions)
+ })
+
+ // IN.MARKET_DEPTH (12)
+ decoder.registerProto(IN.MARKET_DEPTH, (d, buf) => {
+ const proto = MarketDepthProto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ // decode market depth fields
+ if (proto.marketDepthData === undefined) return
+ const data = proto.marketDepthData
+
+ const position = data.position ?? UNSET_INTEGER
+ const operation = data.operation ?? UNSET_INTEGER
+ const side = data.side ?? UNSET_INTEGER
+ const price = data.price ?? UNSET_DOUBLE
+ const size = data.size !== undefined ? new Decimal(data.size) : UNSET_DECIMAL
+
+ d.wrapper.updateMktDepth(reqId, position, operation, side, price, size)
+ })
+
+ // IN.MARKET_DEPTH_L2 (13)
+ decoder.registerProto(IN.MARKET_DEPTH_L2, (d, buf) => {
+ const proto = MarketDepthL2Proto.decode(buf)
+
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ // decode market depth fields
+ if (proto.marketDepthData === undefined) return
+ const data = proto.marketDepthData
+
+ const position = data.position ?? 0
+ const marketMaker = data.marketMaker ?? ''
+ const operation = data.operation ?? UNSET_INTEGER
+ const side = data.side ?? UNSET_INTEGER
+ const price = data.price ?? UNSET_DOUBLE
+ const size = data.size !== undefined ? new Decimal(data.size) : UNSET_DECIMAL
+ const isSmartDepth = data.isSmartDepth ?? false
+
+ d.wrapper.updateMktDepthL2(reqId, position, marketMaker, operation, side, price, size, isSmartDepth)
+ })
+}
diff --git a/packages/ibkr/src/decoder/misc.ts b/packages/ibkr/src/decoder/misc.ts
new file mode 100644
index 00000000..63d39744
--- /dev/null
+++ b/packages/ibkr/src/decoder/misc.ts
@@ -0,0 +1,833 @@
+/**
+ * Miscellaneous decoder handlers (text + protobuf).
+ *
+ * Message types:
+ * IN.ERR_MSG (4)
+ * IN.CURRENT_TIME (49)
+ * IN.CURRENT_TIME_IN_MILLIS (109)
+ * IN.NEWS_BULLETINS (14)
+ * IN.RECEIVE_FA (16)
+ * IN.SCANNER_PARAMETERS (19)
+ * IN.SCANNER_DATA (20)
+ * IN.FUNDAMENTAL_DATA (51)
+ * IN.NEWS_PROVIDERS (85)
+ * IN.NEWS_ARTICLE (83)
+ * IN.TICK_NEWS (84)
+ * IN.HISTORICAL_NEWS (86)
+ * IN.HISTORICAL_NEWS_END (87)
+ * IN.SECURITY_DEFINITION_OPTION_PARAMETER (75)
+ * IN.SECURITY_DEFINITION_OPTION_PARAMETER_END (76)
+ * IN.SOFT_DOLLAR_TIERS (77)
+ * IN.FAMILY_CODES (78)
+ * IN.SMART_COMPONENTS (82)
+ * IN.MKT_DEPTH_EXCHANGES (80)
+ * IN.VERIFY_MESSAGE_API (65)
+ * IN.VERIFY_COMPLETED (66)
+ * IN.VERIFY_AND_AUTH_MESSAGE_API (69)
+ * IN.VERIFY_AND_AUTH_COMPLETED (70)
+ * IN.DISPLAY_GROUP_LIST (67)
+ * IN.DISPLAY_GROUP_UPDATED (68)
+ * IN.WSH_META_DATA (104)
+ * IN.WSH_EVENT_DATA (105)
+ * IN.USER_INFO (107)
+ * IN.REPLACE_FA_END (103)
+ * IN.CONFIG_RESPONSE (110)
+ * IN.UPDATE_CONFIG_RESPONSE (111)
+ */
+
+import type { Decoder } from './base.js'
+import { IN } from '../message.js'
+import { NO_VALID_ID } from '../const.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeBool,
+} from '../utils.js'
+import {
+ MIN_SERVER_VER_ADVANCED_ORDER_REJECT,
+ MIN_SERVER_VER_ERROR_TIME,
+ MIN_SERVER_VER_SERVICE_DATA_TYPE,
+} from '../server-versions.js'
+import { SoftDollarTier } from '../softdollartier.js'
+import {
+ FamilyCode,
+ SmartComponent,
+ DepthMktDataDescription,
+ NewsProvider,
+} from '../common.js'
+import { ScanData } from '../scanner.js'
+import { ContractDetails, Contract } from '../contract.js'
+
+// Protobuf message types
+import { CurrentTime as CurrentTimeProto } from '../protobuf/CurrentTime.js'
+import { CurrentTimeInMillis as CurrentTimeInMillisProto } from '../protobuf/CurrentTimeInMillis.js'
+import { ErrorMessage as ErrorMessageProto } from '../protobuf/ErrorMessage.js'
+import { NewsBulletin as NewsBulletinProto } from '../protobuf/NewsBulletin.js'
+import { ReceiveFA as ReceiveFAProto } from '../protobuf/ReceiveFA.js'
+import { ScannerParameters as ScannerParametersProto } from '../protobuf/ScannerParameters.js'
+import { ScannerData as ScannerDataProto } from '../protobuf/ScannerData.js'
+import { FundamentalsData as FundamentalsDataProto } from '../protobuf/FundamentalsData.js'
+import { NewsProviders as NewsProvidersProto } from '../protobuf/NewsProviders.js'
+import { NewsArticle as NewsArticleProto } from '../protobuf/NewsArticle.js'
+import { TickNews as TickNewsProto } from '../protobuf/TickNews.js'
+import { HistoricalNews as HistoricalNewsProto } from '../protobuf/HistoricalNews.js'
+import { HistoricalNewsEnd as HistoricalNewsEndProto } from '../protobuf/HistoricalNewsEnd.js'
+import { SecDefOptParameter as SecDefOptParameterProto } from '../protobuf/SecDefOptParameter.js'
+import { SecDefOptParameterEnd as SecDefOptParameterEndProto } from '../protobuf/SecDefOptParameterEnd.js'
+import { SoftDollarTiers as SoftDollarTiersProto } from '../protobuf/SoftDollarTiers.js'
+import type { SoftDollarTier as SoftDollarTierProto } from '../protobuf/SoftDollarTier.js'
+import { FamilyCodes as FamilyCodesProto } from '../protobuf/FamilyCodes.js'
+import type { FamilyCode as FamilyCodeProto } from '../protobuf/FamilyCode.js'
+import { SmartComponents as SmartComponentsProto } from '../protobuf/SmartComponents.js'
+import type { SmartComponent as SmartComponentProto } from '../protobuf/SmartComponent.js'
+import { MarketDepthExchanges as MarketDepthExchangesProto } from '../protobuf/MarketDepthExchanges.js'
+import type { DepthMarketDataDescription as DepthMarketDataDescriptionProto } from '../protobuf/DepthMarketDataDescription.js'
+import { VerifyMessageApi as VerifyMessageApiProto } from '../protobuf/VerifyMessageApi.js'
+import { VerifyCompleted as VerifyCompletedProto } from '../protobuf/VerifyCompleted.js'
+import { DisplayGroupList as DisplayGroupListProto } from '../protobuf/DisplayGroupList.js'
+import { DisplayGroupUpdated as DisplayGroupUpdatedProto } from '../protobuf/DisplayGroupUpdated.js'
+import { WshMetaData as WshMetaDataProto } from '../protobuf/WshMetaData.js'
+import { WshEventData as WshEventDataProto } from '../protobuf/WshEventData.js'
+import { UserInfo as UserInfoProto } from '../protobuf/UserInfo.js'
+import { ReplaceFAEnd as ReplaceFAEndProto } from '../protobuf/ReplaceFAEnd.js'
+import { ConfigResponse as ConfigResponseProto } from '../protobuf/ConfigResponse.js'
+import { UpdateConfigResponse as UpdateConfigResponseProto } from '../protobuf/UpdateConfigResponse.js'
+import type { Contract as ContractProto } from '../protobuf/Contract.js'
+
+// ---------------------------------------------------------------------------
+// Protobuf → domain helpers
+// ---------------------------------------------------------------------------
+
+function decodeContractFromProto(cp: ContractProto): Contract {
+ const contract = new Contract()
+ if (cp.conId !== undefined) contract.conId = cp.conId
+ if (cp.symbol !== undefined) contract.symbol = cp.symbol
+ if (cp.secType !== undefined) contract.secType = cp.secType
+ if (cp.lastTradeDateOrContractMonth !== undefined) contract.lastTradeDateOrContractMonth = cp.lastTradeDateOrContractMonth
+ if (cp.strike !== undefined) contract.strike = cp.strike
+ if (cp.right !== undefined) contract.right = cp.right
+ if (cp.multiplier !== undefined) contract.multiplier = String(cp.multiplier)
+ if (cp.exchange !== undefined) contract.exchange = cp.exchange
+ if (cp.currency !== undefined) contract.currency = cp.currency
+ if (cp.localSymbol !== undefined) contract.localSymbol = cp.localSymbol
+ if (cp.tradingClass !== undefined) contract.tradingClass = cp.tradingClass
+ return contract
+}
+
+function decodeSoftDollarTierFromProto(p: SoftDollarTierProto): SoftDollarTier {
+ return new SoftDollarTier(
+ p.name ?? '',
+ p.value ?? '',
+ p.displayName ?? '',
+ )
+}
+
+function decodeFamilyCodeFromProto(p: FamilyCodeProto): FamilyCode {
+ const fc = new FamilyCode()
+ fc.accountID = p.accountId ?? ''
+ fc.familyCodeStr = p.familyCode ?? ''
+ return fc
+}
+
+function decodeSmartComponentFromProto(p: SmartComponentProto): SmartComponent {
+ const sc = new SmartComponent()
+ sc.bitNumber = p.bitNumber ?? 0
+ sc.exchange = p.exchange ?? ''
+ sc.exchangeLetter = p.exchangeLetter ?? ''
+ return sc
+}
+
+function decodeDepthMktDataDescFromProto(p: DepthMarketDataDescriptionProto): DepthMktDataDescription {
+ const desc = new DepthMktDataDescription()
+ desc.exchange = p.exchange ?? ''
+ desc.secType = p.secType ?? ''
+ desc.listingExch = p.listingExch ?? ''
+ desc.serviceDataType = p.serviceDataType ?? ''
+ desc.aggGroup = p.aggGroup ?? 0
+ return desc
+}
+
+// ---------------------------------------------------------------------------
+// Registration
+// ---------------------------------------------------------------------------
+
+export function applyMiscHandlers(decoder: Decoder): void {
+
+ // ========================================================================
+ // Text handlers
+ // ========================================================================
+
+ // --- IN.ERR_MSG (4) ---
+ decoder.registerText(IN.ERR_MSG, (d, fields) => {
+ decodeInt(fields) // msgId
+ if (d.serverVersion < MIN_SERVER_VER_ERROR_TIME) {
+ decodeInt(fields) // version
+ }
+ const reqId = decodeInt(fields)
+ const errorCode = decodeInt(fields)
+ const errorString = decodeStr(fields)
+ let advancedOrderRejectJson = ''
+ if (d.serverVersion >= MIN_SERVER_VER_ADVANCED_ORDER_REJECT) {
+ advancedOrderRejectJson = decodeStr(fields)
+ }
+ let errorTime = 0
+ if (d.serverVersion >= MIN_SERVER_VER_ERROR_TIME) {
+ errorTime = decodeInt(fields)
+ }
+ d.wrapper.error(reqId, errorTime, errorCode, errorString, advancedOrderRejectJson)
+ })
+
+ // --- IN.CURRENT_TIME (49) ---
+ decoder.registerText(IN.CURRENT_TIME, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const time = decodeInt(fields)
+ d.wrapper.currentTime(time)
+ })
+
+ // --- IN.CURRENT_TIME_IN_MILLIS (109) ---
+ decoder.registerText(IN.CURRENT_TIME_IN_MILLIS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const timeInMillis = decodeInt(fields)
+ d.wrapper.currentTimeInMillis(timeInMillis)
+ })
+
+ // --- IN.NEWS_BULLETINS (14) ---
+ decoder.registerText(IN.NEWS_BULLETINS, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const msgId = decodeInt(fields)
+ const msgType = decodeInt(fields)
+ const message = decodeStr(fields)
+ const originExch = decodeStr(fields)
+ d.wrapper.updateNewsBulletin(msgId, msgType, message, originExch)
+ })
+
+ // --- IN.RECEIVE_FA (16) ---
+ decoder.registerText(IN.RECEIVE_FA, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const faDataType = decodeInt(fields)
+ const xml = decodeStr(fields)
+ d.wrapper.receiveFA(faDataType, xml)
+ })
+
+ // --- IN.SCANNER_PARAMETERS (19) ---
+ decoder.registerText(IN.SCANNER_PARAMETERS, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const xml = decodeStr(fields)
+ d.wrapper.scannerParameters(xml)
+ })
+
+ // --- IN.SCANNER_DATA (20) ---
+ decoder.registerText(IN.SCANNER_DATA, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+
+ const numberOfElements = decodeInt(fields)
+
+ for (let i = 0; i < numberOfElements; i++) {
+ const data = new ScanData()
+ const contractDetails = new ContractDetails()
+ data.contract = contractDetails.contract
+
+ data.rank = decodeInt(fields)
+ contractDetails.contract.conId = decodeInt(fields) // ver 3
+ contractDetails.contract.symbol = decodeStr(fields)
+ contractDetails.contract.secType = decodeStr(fields)
+ contractDetails.contract.lastTradeDateOrContractMonth = decodeStr(fields)
+ contractDetails.contract.strike = decodeFloat(fields)
+ contractDetails.contract.right = decodeStr(fields)
+ contractDetails.contract.exchange = decodeStr(fields)
+ contractDetails.contract.currency = decodeStr(fields)
+ contractDetails.contract.localSymbol = decodeStr(fields)
+ contractDetails.marketName = decodeStr(fields)
+ contractDetails.contract.tradingClass = decodeStr(fields)
+ data.distance = decodeStr(fields)
+ data.benchmark = decodeStr(fields)
+ data.projection = decodeStr(fields)
+ data.legsStr = decodeStr(fields)
+ d.wrapper.scannerData(
+ reqId, data.rank, contractDetails,
+ data.distance, data.benchmark, data.projection, data.legsStr,
+ )
+ }
+
+ d.wrapper.scannerDataEnd(reqId)
+ })
+
+ // --- IN.FUNDAMENTAL_DATA (51) ---
+ decoder.registerText(IN.FUNDAMENTAL_DATA, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const data = decodeStr(fields)
+ d.wrapper.fundamentalData(reqId, data)
+ })
+
+ // --- IN.NEWS_PROVIDERS (85) ---
+ decoder.registerText(IN.NEWS_PROVIDERS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const newsProviders: NewsProvider[] = []
+ const nNewsProviders = decodeInt(fields)
+ if (nNewsProviders > 0) {
+ for (let i = 0; i < nNewsProviders; i++) {
+ const provider = new NewsProvider()
+ provider.code = decodeStr(fields)
+ provider.name = decodeStr(fields)
+ newsProviders.push(provider)
+ }
+ }
+ d.wrapper.newsProviders(newsProviders)
+ })
+
+ // --- IN.NEWS_ARTICLE (83) ---
+ decoder.registerText(IN.NEWS_ARTICLE, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const articleType = decodeInt(fields)
+ const articleText = decodeStr(fields)
+ d.wrapper.newsArticle(reqId, articleType, articleText)
+ })
+
+ // --- IN.TICK_NEWS (84) ---
+ decoder.registerText(IN.TICK_NEWS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const tickerId = decodeInt(fields)
+ const timeStamp = decodeInt(fields)
+ const providerCode = decodeStr(fields)
+ const articleId = decodeStr(fields)
+ const headline = decodeStr(fields)
+ const extraData = decodeStr(fields)
+ d.wrapper.tickNews(tickerId, timeStamp, providerCode, articleId, headline, extraData)
+ })
+
+ // --- IN.HISTORICAL_NEWS (86) ---
+ decoder.registerText(IN.HISTORICAL_NEWS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const requestId = decodeInt(fields)
+ const time = decodeStr(fields)
+ const providerCode = decodeStr(fields)
+ const articleId = decodeStr(fields)
+ const headline = decodeStr(fields)
+ d.wrapper.historicalNews(requestId, time, providerCode, articleId, headline)
+ })
+
+ // --- IN.HISTORICAL_NEWS_END (87) ---
+ decoder.registerText(IN.HISTORICAL_NEWS_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const hasMore = decodeBool(fields)
+ d.wrapper.historicalNewsEnd(reqId, hasMore)
+ })
+
+ // --- IN.SECURITY_DEFINITION_OPTION_PARAMETER (75) ---
+ decoder.registerText(IN.SECURITY_DEFINITION_OPTION_PARAMETER, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const exchange = decodeStr(fields)
+ const underlyingConId = decodeInt(fields)
+ const tradingClass = decodeStr(fields)
+ const multiplier = decodeStr(fields)
+
+ const expCount = decodeInt(fields)
+ const expirations = new Set()
+ for (let i = 0; i < expCount; i++) {
+ expirations.add(decodeStr(fields))
+ }
+
+ const strikeCount = decodeInt(fields)
+ const strikes = new Set()
+ for (let i = 0; i < strikeCount; i++) {
+ strikes.add(decodeFloat(fields))
+ }
+
+ d.wrapper.securityDefinitionOptionParameter(
+ reqId, exchange, underlyingConId, tradingClass, multiplier,
+ expirations, strikes,
+ )
+ })
+
+ // --- IN.SECURITY_DEFINITION_OPTION_PARAMETER_END (76) ---
+ decoder.registerText(IN.SECURITY_DEFINITION_OPTION_PARAMETER_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ d.wrapper.securityDefinitionOptionParameterEnd(reqId)
+ })
+
+ // --- IN.SOFT_DOLLAR_TIERS (77) ---
+ decoder.registerText(IN.SOFT_DOLLAR_TIERS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const nTiers = decodeInt(fields)
+
+ const tiers: SoftDollarTier[] = []
+ for (let i = 0; i < nTiers; i++) {
+ const tier = new SoftDollarTier()
+ tier.name = decodeStr(fields)
+ tier.val = decodeStr(fields)
+ tier.displayName = decodeStr(fields)
+ tiers.push(tier)
+ }
+
+ d.wrapper.softDollarTiers(reqId, tiers)
+ })
+
+ // --- IN.FAMILY_CODES (78) ---
+ decoder.registerText(IN.FAMILY_CODES, (d, fields) => {
+ decodeInt(fields) // msgId
+ const nFamilyCodes = decodeInt(fields)
+ const familyCodes: FamilyCode[] = []
+ for (let i = 0; i < nFamilyCodes; i++) {
+ const famCode = new FamilyCode()
+ famCode.accountID = decodeStr(fields)
+ famCode.familyCodeStr = decodeStr(fields)
+ familyCodes.push(famCode)
+ }
+ d.wrapper.familyCodes(familyCodes)
+ })
+
+ // --- IN.SMART_COMPONENTS (82) ---
+ decoder.registerText(IN.SMART_COMPONENTS, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const n = decodeInt(fields)
+
+ const smartComponentMap: SmartComponent[] = []
+ for (let i = 0; i < n; i++) {
+ const smartComponent = new SmartComponent()
+ smartComponent.bitNumber = decodeInt(fields)
+ smartComponent.exchange = decodeStr(fields)
+ smartComponent.exchangeLetter = decodeStr(fields)
+ smartComponentMap.push(smartComponent)
+ }
+
+ d.wrapper.smartComponents(reqId, smartComponentMap)
+ })
+
+ // --- IN.MKT_DEPTH_EXCHANGES (80) ---
+ decoder.registerText(IN.MKT_DEPTH_EXCHANGES, (d, fields) => {
+ decodeInt(fields) // msgId
+ const depthMktDataDescriptions: DepthMktDataDescription[] = []
+ const nDepthMktDataDescriptions = decodeInt(fields)
+
+ if (nDepthMktDataDescriptions > 0) {
+ for (let i = 0; i < nDepthMktDataDescriptions; i++) {
+ const desc = new DepthMktDataDescription()
+ desc.exchange = decodeStr(fields)
+ desc.secType = decodeStr(fields)
+ if (d.serverVersion >= MIN_SERVER_VER_SERVICE_DATA_TYPE) {
+ desc.listingExch = decodeStr(fields)
+ desc.serviceDataType = decodeStr(fields)
+ desc.aggGroup = decodeInt(fields)
+ } else {
+ decodeInt(fields) // boolean notSuppIsL2
+ }
+ depthMktDataDescriptions.push(desc)
+ }
+ }
+
+ d.wrapper.mktDepthExchanges(depthMktDataDescriptions)
+ })
+
+ // --- IN.VERIFY_MESSAGE_API (65) ---
+ decoder.registerText(IN.VERIFY_MESSAGE_API, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const apiData = decodeStr(fields)
+ d.wrapper.verifyMessageAPI(apiData)
+ })
+
+ // --- IN.VERIFY_COMPLETED (66) ---
+ decoder.registerText(IN.VERIFY_COMPLETED, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const isSuccessful = decodeBool(fields)
+ const errorText = decodeStr(fields)
+ d.wrapper.verifyCompleted(isSuccessful, errorText)
+ })
+
+ // --- IN.VERIFY_AND_AUTH_MESSAGE_API (69) ---
+ decoder.registerText(IN.VERIFY_AND_AUTH_MESSAGE_API, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const apiData = decodeStr(fields)
+ const xyzChallenge = decodeStr(fields)
+ d.wrapper.verifyAndAuthMessageAPI(apiData, xyzChallenge)
+ })
+
+ // --- IN.VERIFY_AND_AUTH_COMPLETED (70) ---
+ decoder.registerText(IN.VERIFY_AND_AUTH_COMPLETED, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const isSuccessful = decodeBool(fields)
+ const errorText = decodeStr(fields)
+ d.wrapper.verifyAndAuthCompleted(isSuccessful, errorText)
+ })
+
+ // --- IN.DISPLAY_GROUP_LIST (67) ---
+ decoder.registerText(IN.DISPLAY_GROUP_LIST, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const groups = decodeStr(fields)
+ d.wrapper.displayGroupList(reqId, groups)
+ })
+
+ // --- IN.DISPLAY_GROUP_UPDATED (68) ---
+ decoder.registerText(IN.DISPLAY_GROUP_UPDATED, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const reqId = decodeInt(fields)
+ const contractInfo = decodeStr(fields)
+ d.wrapper.displayGroupUpdated(reqId, contractInfo)
+ })
+
+ // --- IN.WSH_META_DATA (104) ---
+ decoder.registerText(IN.WSH_META_DATA, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const dataJson = decodeStr(fields)
+ d.wrapper.wshMetaData(reqId, dataJson)
+ })
+
+ // --- IN.WSH_EVENT_DATA (105) ---
+ decoder.registerText(IN.WSH_EVENT_DATA, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const dataJson = decodeStr(fields)
+ d.wrapper.wshEventData(reqId, dataJson)
+ })
+
+ // --- IN.USER_INFO (107) ---
+ decoder.registerText(IN.USER_INFO, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const whiteBrandingId = decodeStr(fields)
+ d.wrapper.userInfo(reqId, whiteBrandingId)
+ })
+
+ // --- IN.REPLACE_FA_END (103) ---
+ decoder.registerText(IN.REPLACE_FA_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ const reqId = decodeInt(fields)
+ const text = decodeStr(fields)
+ d.wrapper.replaceFAEnd(reqId, text)
+ })
+
+ // ========================================================================
+ // Protobuf handlers
+ // ========================================================================
+
+ // --- IN.ERR_MSG (4) ---
+ decoder.registerProto(IN.ERR_MSG, (d, buf) => {
+ const proto = ErrorMessageProto.decode(buf)
+ d.wrapper.error(
+ proto.id ?? -1,
+ proto.errorTime ?? 0,
+ proto.errorCode ?? 0,
+ proto.errorMsg ?? '',
+ proto.advancedOrderRejectJson ?? '',
+ )
+ })
+
+ // --- IN.CURRENT_TIME (49) ---
+ decoder.registerProto(IN.CURRENT_TIME, (d, buf) => {
+ const proto = CurrentTimeProto.decode(buf)
+ d.wrapper.currentTime(proto.currentTime ?? 0)
+ })
+
+ // --- IN.CURRENT_TIME_IN_MILLIS (109) ---
+ decoder.registerProto(IN.CURRENT_TIME_IN_MILLIS, (d, buf) => {
+ const proto = CurrentTimeInMillisProto.decode(buf)
+ d.wrapper.currentTimeInMillis(proto.currentTimeInMillis ?? 0)
+ })
+
+ // --- IN.NEWS_BULLETINS (14) ---
+ decoder.registerProto(IN.NEWS_BULLETINS, (d, buf) => {
+ const proto = NewsBulletinProto.decode(buf)
+ d.wrapper.updateNewsBulletin(
+ proto.newsMsgId ?? 0,
+ proto.newsMsgType ?? 0,
+ proto.newsMessage ?? '',
+ proto.originatingExch ?? '',
+ )
+ })
+
+ // --- IN.RECEIVE_FA (16) ---
+ decoder.registerProto(IN.RECEIVE_FA, (d, buf) => {
+ const proto = ReceiveFAProto.decode(buf)
+ d.wrapper.receiveFA(
+ proto.faDataType ?? 0,
+ proto.xml ?? '',
+ )
+ })
+
+ // --- IN.SCANNER_PARAMETERS (19) ---
+ decoder.registerProto(IN.SCANNER_PARAMETERS, (d, buf) => {
+ const proto = ScannerParametersProto.decode(buf)
+ d.wrapper.scannerParameters(proto.xml ?? '')
+ })
+
+ // --- IN.SCANNER_DATA (20) ---
+ decoder.registerProto(IN.SCANNER_DATA, (d, buf) => {
+ const proto = ScannerDataProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+
+ if (proto.scannerDataElement) {
+ for (const element of proto.scannerDataElement) {
+ const rank = element.rank ?? 0
+ const contractDetails = new ContractDetails()
+ if (element.contract) {
+ contractDetails.contract = decodeContractFromProto(element.contract)
+ contractDetails.marketName = element.marketName ?? ''
+ }
+ const distance = element.distance ?? ''
+ const benchmark = element.benchmark ?? ''
+ const projection = element.projection ?? ''
+ const comboKey = element.comboKey ?? ''
+
+ d.wrapper.scannerData(reqId, rank, contractDetails, distance, benchmark, projection, comboKey)
+ }
+ }
+
+ d.wrapper.scannerDataEnd(reqId)
+ })
+
+ // --- IN.FUNDAMENTAL_DATA (51) ---
+ decoder.registerProto(IN.FUNDAMENTAL_DATA, (d, buf) => {
+ const proto = FundamentalsDataProto.decode(buf)
+ d.wrapper.fundamentalData(
+ proto.reqId ?? NO_VALID_ID,
+ proto.data ?? '',
+ )
+ })
+
+ // --- IN.NEWS_PROVIDERS (85) ---
+ decoder.registerProto(IN.NEWS_PROVIDERS, (d, buf) => {
+ const proto = NewsProvidersProto.decode(buf)
+ const newsProviders: NewsProvider[] = []
+ if (proto.newsProviders) {
+ for (const np of proto.newsProviders) {
+ const provider = new NewsProvider()
+ provider.code = np.providerCode ?? ''
+ provider.name = np.providerName ?? ''
+ newsProviders.push(provider)
+ }
+ }
+ d.wrapper.newsProviders(newsProviders)
+ })
+
+ // --- IN.NEWS_ARTICLE (83) ---
+ decoder.registerProto(IN.NEWS_ARTICLE, (d, buf) => {
+ const proto = NewsArticleProto.decode(buf)
+ d.wrapper.newsArticle(
+ proto.reqId ?? NO_VALID_ID,
+ proto.articleType ?? 0,
+ proto.articleText ?? '',
+ )
+ })
+
+ // --- IN.TICK_NEWS (84) ---
+ decoder.registerProto(IN.TICK_NEWS, (d, buf) => {
+ const proto = TickNewsProto.decode(buf)
+ d.wrapper.tickNews(
+ proto.reqId ?? NO_VALID_ID,
+ proto.timestamp ?? 0,
+ proto.providerCode ?? '',
+ proto.articleId ?? '',
+ proto.headline ?? '',
+ proto.extraData ?? '',
+ )
+ })
+
+ // --- IN.HISTORICAL_NEWS (86) ---
+ decoder.registerProto(IN.HISTORICAL_NEWS, (d, buf) => {
+ const proto = HistoricalNewsProto.decode(buf)
+ d.wrapper.historicalNews(
+ proto.reqId ?? NO_VALID_ID,
+ proto.time ?? '',
+ proto.providerCode ?? '',
+ proto.articleId ?? '',
+ proto.headline ?? '',
+ )
+ })
+
+ // --- IN.HISTORICAL_NEWS_END (87) ---
+ decoder.registerProto(IN.HISTORICAL_NEWS_END, (d, buf) => {
+ const proto = HistoricalNewsEndProto.decode(buf)
+ d.wrapper.historicalNewsEnd(
+ proto.reqId ?? NO_VALID_ID,
+ proto.hasMore ?? false,
+ )
+ })
+
+ // --- IN.SECURITY_DEFINITION_OPTION_PARAMETER (75) ---
+ decoder.registerProto(IN.SECURITY_DEFINITION_OPTION_PARAMETER, (d, buf) => {
+ const proto = SecDefOptParameterProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const exchange = proto.exchange ?? ''
+ const underlyingConId = proto.underlyingConId ?? 0
+ const tradingClass = proto.tradingClass ?? ''
+ const multiplier = proto.multiplier ?? ''
+
+ const expirations = new Set()
+ if (proto.expirations) {
+ for (const exp of proto.expirations) {
+ expirations.add(exp)
+ }
+ }
+
+ const strikes = new Set()
+ if (proto.strikes) {
+ for (const strike of proto.strikes) {
+ strikes.add(strike)
+ }
+ }
+
+ d.wrapper.securityDefinitionOptionParameter(
+ reqId, exchange, underlyingConId, tradingClass, multiplier,
+ expirations, strikes,
+ )
+ })
+
+ // --- IN.SECURITY_DEFINITION_OPTION_PARAMETER_END (76) ---
+ decoder.registerProto(IN.SECURITY_DEFINITION_OPTION_PARAMETER_END, (d, buf) => {
+ const proto = SecDefOptParameterEndProto.decode(buf)
+ d.wrapper.securityDefinitionOptionParameterEnd(proto.reqId ?? NO_VALID_ID)
+ })
+
+ // --- IN.SOFT_DOLLAR_TIERS (77) ---
+ decoder.registerProto(IN.SOFT_DOLLAR_TIERS, (d, buf) => {
+ const proto = SoftDollarTiersProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const tiers: SoftDollarTier[] = []
+ if (proto.softDollarTiers) {
+ for (const tierProto of proto.softDollarTiers) {
+ tiers.push(decodeSoftDollarTierFromProto(tierProto))
+ }
+ }
+ d.wrapper.softDollarTiers(reqId, tiers)
+ })
+
+ // --- IN.FAMILY_CODES (78) ---
+ decoder.registerProto(IN.FAMILY_CODES, (d, buf) => {
+ const proto = FamilyCodesProto.decode(buf)
+ const familyCodes: FamilyCode[] = []
+ if (proto.familyCodes) {
+ for (const fcProto of proto.familyCodes) {
+ familyCodes.push(decodeFamilyCodeFromProto(fcProto))
+ }
+ }
+ d.wrapper.familyCodes(familyCodes)
+ })
+
+ // --- IN.SMART_COMPONENTS (82) ---
+ decoder.registerProto(IN.SMART_COMPONENTS, (d, buf) => {
+ const proto = SmartComponentsProto.decode(buf)
+ const reqId = proto.reqId ?? NO_VALID_ID
+ const smartComponentsMap: SmartComponent[] = []
+ if (proto.smartComponents) {
+ for (const scProto of proto.smartComponents) {
+ smartComponentsMap.push(decodeSmartComponentFromProto(scProto))
+ }
+ }
+ d.wrapper.smartComponents(reqId, smartComponentsMap)
+ })
+
+ // --- IN.MKT_DEPTH_EXCHANGES (80) ---
+ decoder.registerProto(IN.MKT_DEPTH_EXCHANGES, (d, buf) => {
+ const proto = MarketDepthExchangesProto.decode(buf)
+ const depthMktDataDescriptions: DepthMktDataDescription[] = []
+ if (proto.depthMarketDataDescriptions) {
+ for (const descProto of proto.depthMarketDataDescriptions) {
+ depthMktDataDescriptions.push(decodeDepthMktDataDescFromProto(descProto))
+ }
+ }
+ d.wrapper.mktDepthExchanges(depthMktDataDescriptions)
+ })
+
+ // --- IN.VERIFY_MESSAGE_API (65) ---
+ decoder.registerProto(IN.VERIFY_MESSAGE_API, (d, buf) => {
+ const proto = VerifyMessageApiProto.decode(buf)
+ d.wrapper.verifyMessageAPI(proto.apiData ?? '')
+ })
+
+ // --- IN.VERIFY_COMPLETED (66) ---
+ decoder.registerProto(IN.VERIFY_COMPLETED, (d, buf) => {
+ const proto = VerifyCompletedProto.decode(buf)
+ d.wrapper.verifyCompleted(
+ proto.isSuccessful ?? false,
+ proto.errorText ?? '',
+ )
+ })
+
+ // --- IN.DISPLAY_GROUP_LIST (67) ---
+ decoder.registerProto(IN.DISPLAY_GROUP_LIST, (d, buf) => {
+ const proto = DisplayGroupListProto.decode(buf)
+ d.wrapper.displayGroupList(
+ proto.reqId ?? NO_VALID_ID,
+ proto.groups ?? '',
+ )
+ })
+
+ // --- IN.DISPLAY_GROUP_UPDATED (68) ---
+ decoder.registerProto(IN.DISPLAY_GROUP_UPDATED, (d, buf) => {
+ const proto = DisplayGroupUpdatedProto.decode(buf)
+ d.wrapper.displayGroupUpdated(
+ proto.reqId ?? NO_VALID_ID,
+ proto.contractInfo ?? '',
+ )
+ })
+
+ // --- IN.WSH_META_DATA (104) ---
+ decoder.registerProto(IN.WSH_META_DATA, (d, buf) => {
+ const proto = WshMetaDataProto.decode(buf)
+ d.wrapper.wshMetaData(
+ proto.reqId ?? NO_VALID_ID,
+ proto.dataJson ?? '',
+ )
+ })
+
+ // --- IN.WSH_EVENT_DATA (105) ---
+ decoder.registerProto(IN.WSH_EVENT_DATA, (d, buf) => {
+ const proto = WshEventDataProto.decode(buf)
+ d.wrapper.wshEventData(
+ proto.reqId ?? NO_VALID_ID,
+ proto.dataJson ?? '',
+ )
+ })
+
+ // --- IN.USER_INFO (107) ---
+ decoder.registerProto(IN.USER_INFO, (d, buf) => {
+ const proto = UserInfoProto.decode(buf)
+ d.wrapper.userInfo(
+ proto.reqId ?? NO_VALID_ID,
+ proto.whiteBrandingId ?? '',
+ )
+ })
+
+ // --- IN.REPLACE_FA_END (103) ---
+ decoder.registerProto(IN.REPLACE_FA_END, (d, buf) => {
+ const proto = ReplaceFAEndProto.decode(buf)
+ d.wrapper.replaceFAEnd(
+ proto.reqId ?? NO_VALID_ID,
+ proto.text ?? '',
+ )
+ })
+
+ // --- IN.CONFIG_RESPONSE (110) --- proto only
+ decoder.registerProto(IN.CONFIG_RESPONSE, (d, buf) => {
+ const proto = ConfigResponseProto.decode(buf)
+ d.wrapper.configResponseProtoBuf(proto)
+ })
+
+ // --- IN.UPDATE_CONFIG_RESPONSE (111) --- proto only
+ decoder.registerProto(IN.UPDATE_CONFIG_RESPONSE, (d, buf) => {
+ const proto = UpdateConfigResponseProto.decode(buf)
+ d.wrapper.updateConfigResponseProtoBuf(proto)
+ })
+}
diff --git a/packages/ibkr/src/decoder/orders.ts b/packages/ibkr/src/decoder/orders.ts
new file mode 100644
index 00000000..b2403085
--- /dev/null
+++ b/packages/ibkr/src/decoder/orders.ts
@@ -0,0 +1,789 @@
+/**
+ * Order-related message handlers (text + protobuf).
+ *
+ * Message types handled:
+ * IN.ORDER_STATUS (3)
+ * IN.OPEN_ORDER (5)
+ * IN.OPEN_ORDER_END (53)
+ * IN.ORDER_BOUND (100)
+ * IN.COMPLETED_ORDER (101)
+ * IN.COMPLETED_ORDERS_END (102)
+ * IN.NEXT_VALID_ID (9)
+ */
+
+import Decimal from 'decimal.js'
+import type { Decoder } from './base.js'
+import { IN } from '../message.js'
+import { UNSET_INTEGER, UNSET_DOUBLE, UNSET_DECIMAL } from '../const.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeDecimal,
+ floatMaxString,
+ decimalMaxString,
+ isValidIntValue,
+} from '../utils.js'
+import {
+ MIN_SERVER_VER_MARKET_CAP_PRICE,
+ MIN_SERVER_VER_ORDER_CONTAINER,
+ MIN_SERVER_VER_AUTO_CANCEL_PARENT,
+ MIN_SERVER_VER_IMBALANCE_ONLY,
+} from '../server-versions.js'
+import { OrderDecoder } from '../order-decoder.js'
+import { Contract, ComboLeg, DeltaNeutralContract } from '../contract.js'
+import { Order, OrderComboLeg } from '../order.js'
+import { OrderState, OrderAllocation } from '../order-state.js'
+import { SoftDollarTier } from '../softdollartier.js'
+import { TagValue } from '../tag-value.js'
+import {
+ OrderCondition,
+ PriceCondition,
+ TimeCondition,
+ MarginCondition,
+ ExecutionCondition,
+ VolumeCondition,
+ PercentChangeCondition,
+} from '../order-condition.js'
+
+// Protobuf message types
+import { OrderStatus as OrderStatusProto } from '../protobuf/OrderStatus.js'
+import { OpenOrder as OpenOrderProto } from '../protobuf/OpenOrder.js'
+import { OpenOrdersEnd as OpenOrdersEndProto } from '../protobuf/OpenOrdersEnd.js'
+import { OrderBound as OrderBoundProto } from '../protobuf/OrderBound.js'
+import { CompletedOrder as CompletedOrderProto } from '../protobuf/CompletedOrder.js'
+import { CompletedOrdersEnd as CompletedOrdersEndProto } from '../protobuf/CompletedOrdersEnd.js'
+import { NextValidId as NextValidIdProto } from '../protobuf/NextValidId.js'
+
+import type { Contract as ContractProto } from '../protobuf/Contract.js'
+import type { Order as OrderProtoType } from '../protobuf/Order.js'
+import type { OrderState as OrderStateProto } from '../protobuf/OrderState.js'
+import type { OrderCondition as OrderConditionProto } from '../protobuf/OrderCondition.js'
+
+// ---------------------------------------------------------------------------
+// Protobuf → data-model conversion helpers
+// (mirrors decoder_utils.py: decodeContract, decodeOrder, decodeOrderState)
+// ---------------------------------------------------------------------------
+
+function decodeContractFromProto(cp: ContractProto): Contract {
+ const contract = new Contract()
+ if (cp.conId !== undefined) contract.conId = cp.conId
+ if (cp.symbol !== undefined) contract.symbol = cp.symbol
+ if (cp.secType !== undefined) contract.secType = cp.secType
+ if (cp.lastTradeDateOrContractMonth !== undefined) contract.lastTradeDateOrContractMonth = cp.lastTradeDateOrContractMonth
+ if (cp.strike !== undefined) contract.strike = cp.strike
+ if (cp.right !== undefined) contract.right = cp.right
+ if (cp.multiplier !== undefined) contract.multiplier = floatMaxString(cp.multiplier)
+ if (cp.exchange !== undefined) contract.exchange = cp.exchange
+ if (cp.currency !== undefined) contract.currency = cp.currency
+ if (cp.localSymbol !== undefined) contract.localSymbol = cp.localSymbol
+ if (cp.tradingClass !== undefined) contract.tradingClass = cp.tradingClass
+ if (cp.comboLegsDescrip !== undefined) contract.comboLegsDescrip = cp.comboLegsDescrip
+
+ // combo legs
+ if (cp.comboLegs && cp.comboLegs.length > 0) {
+ const legs: ComboLeg[] = []
+ for (const clp of cp.comboLegs) {
+ const leg = new ComboLeg()
+ if (clp.conId !== undefined) leg.conId = clp.conId
+ if (clp.ratio !== undefined) leg.ratio = clp.ratio
+ if (clp.action !== undefined) leg.action = clp.action
+ if (clp.exchange !== undefined) leg.exchange = clp.exchange
+ if (clp.openClose !== undefined) leg.openClose = clp.openClose
+ if (clp.shortSalesSlot !== undefined) leg.shortSaleSlot = clp.shortSalesSlot
+ if (clp.designatedLocation !== undefined) leg.designatedLocation = clp.designatedLocation
+ if (clp.exemptCode !== undefined) leg.exemptCode = clp.exemptCode
+ legs.push(leg)
+ }
+ contract.comboLegs = legs
+ }
+
+ // delta neutral contract
+ if (cp.deltaNeutralContract !== undefined) {
+ const dnc = new DeltaNeutralContract()
+ const dnp = cp.deltaNeutralContract
+ if (dnp.conId !== undefined) dnc.conId = dnp.conId
+ if (dnp.delta !== undefined) dnc.delta = dnp.delta
+ if (dnp.price !== undefined) dnc.price = dnp.price
+ contract.deltaNeutralContract = dnc
+ }
+
+ if (cp.lastTradeDate !== undefined) contract.lastTradeDate = cp.lastTradeDate
+ if (cp.primaryExch !== undefined) contract.primaryExchange = cp.primaryExch
+ if (cp.issuerId !== undefined) contract.issuerId = cp.issuerId
+ if (cp.description !== undefined) contract.description = cp.description
+
+ return contract
+}
+
+function decodeOrderComboLegsFromProto(cp: ContractProto): OrderComboLeg[] {
+ const result: OrderComboLeg[] = []
+ if (cp.comboLegs && cp.comboLegs.length > 0) {
+ for (const clp of cp.comboLegs) {
+ const ocl = new OrderComboLeg()
+ if (clp.perLegPrice !== undefined) ocl.price = clp.perLegPrice
+ result.push(ocl)
+ }
+ }
+ return result
+}
+
+function decodeTagValueMap(protoMap: { [key: string]: string } | undefined): TagValue[] | null {
+ if (!protoMap) return null
+ const entries = Object.entries(protoMap)
+ if (entries.length === 0) return null
+ return entries.map(([tag, value]) => new TagValue(tag, value))
+}
+
+function decodeConditionsFromProto(conditions: OrderConditionProto[] | undefined): OrderCondition[] {
+ if (!conditions || conditions.length === 0) return []
+ const result: OrderCondition[] = []
+
+ for (const ocp of conditions) {
+ const conditionType = ocp.type ?? 0
+ let condition: OrderCondition | null = null
+
+ if (conditionType === OrderCondition.Price) {
+ const c = new PriceCondition()
+ setContractConditionFields(ocp, c)
+ if (ocp.price !== undefined) c.price = ocp.price
+ if (ocp.triggerMethod !== undefined) c.triggerMethod = ocp.triggerMethod
+ condition = c
+ } else if (conditionType === OrderCondition.Time) {
+ const c = new TimeCondition()
+ setOperatorConditionFields(ocp, c)
+ if (ocp.time !== undefined) c.time = ocp.time
+ condition = c
+ } else if (conditionType === OrderCondition.Margin) {
+ const c = new MarginCondition()
+ setOperatorConditionFields(ocp, c)
+ if (ocp.percent !== undefined) c.percent = ocp.percent
+ condition = c
+ } else if (conditionType === OrderCondition.Execution) {
+ const c = new ExecutionCondition()
+ setConditionFields(ocp, c)
+ if (ocp.secType !== undefined) c.secType = ocp.secType
+ if (ocp.exchange !== undefined) c.exchange = ocp.exchange
+ if (ocp.symbol !== undefined) c.symbol = ocp.symbol
+ condition = c
+ } else if (conditionType === OrderCondition.Volume) {
+ const c = new VolumeCondition()
+ setContractConditionFields(ocp, c)
+ if (ocp.volume !== undefined) c.volume = ocp.volume
+ condition = c
+ } else if (conditionType === OrderCondition.PercentChange) {
+ const c = new PercentChangeCondition()
+ setContractConditionFields(ocp, c)
+ if (ocp.changePercent !== undefined) c.changePercent = ocp.changePercent
+ condition = c
+ }
+
+ if (condition) result.push(condition)
+ }
+
+ return result
+}
+
+function setConditionFields(ocp: OrderConditionProto, cond: OrderCondition): void {
+ if (ocp.isConjunctionConnection !== undefined) cond.isConjunctionConnection = ocp.isConjunctionConnection
+}
+
+function setOperatorConditionFields(ocp: OrderConditionProto, cond: { isMore: boolean | null; isConjunctionConnection: boolean }): void {
+ if (ocp.isConjunctionConnection !== undefined) cond.isConjunctionConnection = ocp.isConjunctionConnection
+ if (ocp.isMore !== undefined) cond.isMore = ocp.isMore
+}
+
+function setContractConditionFields(ocp: OrderConditionProto, cond: { conId: number | null; exchange: string | null; isMore: boolean | null; isConjunctionConnection: boolean }): void {
+ setOperatorConditionFields(ocp, cond)
+ if (ocp.conId !== undefined) cond.conId = ocp.conId
+ if (ocp.exchange !== undefined) cond.exchange = ocp.exchange
+}
+
+function decodeSoftDollarTierFromProto(op: OrderProtoType): SoftDollarTier | null {
+ const sdtp = op.softDollarTier
+ if (!sdtp) return null
+ return new SoftDollarTier(
+ sdtp.name ?? '',
+ sdtp.value ?? '',
+ sdtp.displayName ?? '',
+ )
+}
+
+function decodeOrderFromProto(orderId: number, cp: ContractProto, op: OrderProtoType): Order {
+ const order = new Order()
+ if (isValidIntValue(orderId)) order.orderId = orderId
+ if (op.orderId !== undefined) order.orderId = op.orderId
+ if (op.action !== undefined) order.action = op.action
+ if (op.totalQuantity !== undefined) order.totalQuantity = new Decimal(op.totalQuantity)
+ if (op.orderType !== undefined) order.orderType = op.orderType
+ if (op.lmtPrice !== undefined) order.lmtPrice = op.lmtPrice
+ if (op.auxPrice !== undefined) order.auxPrice = op.auxPrice
+ if (op.tif !== undefined) order.tif = op.tif
+ if (op.ocaGroup !== undefined) order.ocaGroup = op.ocaGroup
+ if (op.account !== undefined) order.account = op.account
+ if (op.openClose !== undefined) order.openClose = op.openClose
+ if (op.origin !== undefined) order.origin = op.origin
+ if (op.orderRef !== undefined) order.orderRef = op.orderRef
+ if (op.clientId !== undefined) order.clientId = op.clientId
+ if (op.permId !== undefined) order.permId = op.permId
+ if (op.outsideRth !== undefined) order.outsideRth = op.outsideRth
+ if (op.hidden !== undefined) order.hidden = op.hidden
+ if (op.discretionaryAmt !== undefined) order.discretionaryAmt = op.discretionaryAmt
+ if (op.goodAfterTime !== undefined) order.goodAfterTime = op.goodAfterTime
+ if (op.faGroup !== undefined) order.faGroup = op.faGroup
+ if (op.faMethod !== undefined) order.faMethod = op.faMethod
+ if (op.faPercentage !== undefined) order.faPercentage = op.faPercentage
+ if (op.modelCode !== undefined) order.modelCode = op.modelCode
+ if (op.goodTillDate !== undefined) order.goodTillDate = op.goodTillDate
+ if (op.rule80A !== undefined) order.rule80A = op.rule80A
+ if (op.percentOffset !== undefined) order.percentOffset = op.percentOffset
+ if (op.settlingFirm !== undefined) order.settlingFirm = op.settlingFirm
+ if (op.shortSaleSlot !== undefined) order.shortSaleSlot = op.shortSaleSlot
+ if (op.designatedLocation !== undefined) order.designatedLocation = op.designatedLocation
+ if (op.exemptCode !== undefined) order.exemptCode = op.exemptCode
+ if (op.startingPrice !== undefined) order.startingPrice = op.startingPrice
+ if (op.stockRefPrice !== undefined) order.stockRefPrice = op.stockRefPrice
+ if (op.delta !== undefined) order.delta = op.delta
+ if (op.stockRangeLower !== undefined) order.stockRangeLower = op.stockRangeLower
+ if (op.stockRangeUpper !== undefined) order.stockRangeUpper = op.stockRangeUpper
+ if (op.displaySize !== undefined) order.displaySize = op.displaySize
+ if (op.blockOrder !== undefined) order.blockOrder = op.blockOrder
+ if (op.sweepToFill !== undefined) order.sweepToFill = op.sweepToFill
+ if (op.allOrNone !== undefined) order.allOrNone = op.allOrNone
+ if (op.minQty !== undefined) order.minQty = op.minQty
+ if (op.ocaType !== undefined) order.ocaType = op.ocaType
+ if (op.parentId !== undefined) order.parentId = op.parentId
+ if (op.triggerMethod !== undefined) order.triggerMethod = op.triggerMethod
+ if (op.volatility !== undefined) order.volatility = op.volatility
+ if (op.volatilityType !== undefined) order.volatilityType = op.volatilityType
+ if (op.deltaNeutralOrderType !== undefined) order.deltaNeutralOrderType = op.deltaNeutralOrderType
+ if (op.deltaNeutralAuxPrice !== undefined) order.deltaNeutralAuxPrice = op.deltaNeutralAuxPrice
+ if (op.deltaNeutralConId !== undefined) order.deltaNeutralConId = op.deltaNeutralConId
+ if (op.deltaNeutralSettlingFirm !== undefined) order.deltaNeutralSettlingFirm = op.deltaNeutralSettlingFirm
+ if (op.deltaNeutralClearingAccount !== undefined) order.deltaNeutralClearingAccount = op.deltaNeutralClearingAccount
+ if (op.deltaNeutralClearingIntent !== undefined) order.deltaNeutralClearingIntent = op.deltaNeutralClearingIntent
+ if (op.deltaNeutralOpenClose !== undefined) order.deltaNeutralOpenClose = op.deltaNeutralOpenClose
+ if (op.deltaNeutralShortSale !== undefined) order.deltaNeutralShortSale = op.deltaNeutralShortSale
+ if (op.deltaNeutralShortSaleSlot !== undefined) order.deltaNeutralShortSaleSlot = op.deltaNeutralShortSaleSlot
+ if (op.deltaNeutralDesignatedLocation !== undefined) order.deltaNeutralDesignatedLocation = op.deltaNeutralDesignatedLocation
+ if (op.continuousUpdate !== undefined) order.continuousUpdate = op.continuousUpdate
+ if (op.referencePriceType !== undefined) order.referencePriceType = op.referencePriceType
+ if (op.trailStopPrice !== undefined) order.trailStopPrice = op.trailStopPrice
+ if (op.trailingPercent !== undefined) order.trailingPercent = op.trailingPercent
+
+ // order combo legs
+ const orderComboLegs = decodeOrderComboLegsFromProto(cp)
+ if (orderComboLegs.length > 0) order.orderComboLegs = orderComboLegs
+
+ // smart combo routing params
+ order.smartComboRoutingParams = decodeTagValueMap(op.smartComboRoutingParams)
+
+ if (op.scaleInitLevelSize !== undefined) order.scaleInitLevelSize = op.scaleInitLevelSize
+ if (op.scaleSubsLevelSize !== undefined) order.scaleSubsLevelSize = op.scaleSubsLevelSize
+ if (op.scalePriceIncrement !== undefined) order.scalePriceIncrement = op.scalePriceIncrement
+ if (op.scalePriceAdjustValue !== undefined) order.scalePriceAdjustValue = op.scalePriceAdjustValue
+ if (op.scalePriceAdjustInterval !== undefined) order.scalePriceAdjustInterval = op.scalePriceAdjustInterval
+ if (op.scaleProfitOffset !== undefined) order.scaleProfitOffset = op.scaleProfitOffset
+ if (op.scaleAutoReset !== undefined) order.scaleAutoReset = op.scaleAutoReset
+ if (op.scaleInitPosition !== undefined) order.scaleInitPosition = op.scaleInitPosition
+ if (op.scaleInitFillQty !== undefined) order.scaleInitFillQty = op.scaleInitFillQty
+ if (op.scaleRandomPercent !== undefined) order.scaleRandomPercent = op.scaleRandomPercent
+ if (op.hedgeType !== undefined) order.hedgeType = op.hedgeType
+ if (op.hedgeType !== undefined && op.hedgeParam !== undefined && op.hedgeType) order.hedgeParam = op.hedgeParam
+ if (op.optOutSmartRouting !== undefined) order.optOutSmartRouting = op.optOutSmartRouting
+ if (op.clearingAccount !== undefined) order.clearingAccount = op.clearingAccount
+ if (op.clearingIntent !== undefined) order.clearingIntent = op.clearingIntent
+ if (op.notHeld !== undefined) order.notHeld = op.notHeld
+
+ if (op.algoStrategy !== undefined) {
+ order.algoStrategy = op.algoStrategy
+ order.algoParams = decodeTagValueMap(op.algoParams)
+ }
+
+ if (op.solicited !== undefined) order.solicited = op.solicited
+ if (op.whatIf !== undefined) order.whatIf = op.whatIf
+ if (op.randomizeSize !== undefined) order.randomizeSize = op.randomizeSize
+ if (op.randomizePrice !== undefined) order.randomizePrice = op.randomizePrice
+ if (op.referenceContractId !== undefined) order.referenceContractId = op.referenceContractId
+ if (op.isPeggedChangeAmountDecrease !== undefined) order.isPeggedChangeAmountDecrease = op.isPeggedChangeAmountDecrease
+ if (op.peggedChangeAmount !== undefined) order.peggedChangeAmount = op.peggedChangeAmount
+ if (op.referenceChangeAmount !== undefined) order.referenceChangeAmount = op.referenceChangeAmount
+ if (op.referenceExchangeId !== undefined) order.referenceExchangeId = op.referenceExchangeId
+
+ // conditions
+ const conditions = decodeConditionsFromProto(op.conditions)
+ if (conditions.length > 0) order.conditions = conditions
+ if (op.conditionsIgnoreRth !== undefined) order.conditionsIgnoreRth = op.conditionsIgnoreRth
+ if (op.conditionsCancelOrder !== undefined) order.conditionsCancelOrder = op.conditionsCancelOrder
+
+ if (op.adjustedOrderType !== undefined) order.adjustedOrderType = op.adjustedOrderType
+ if (op.triggerPrice !== undefined) order.triggerPrice = op.triggerPrice
+ if (op.lmtPriceOffset !== undefined) order.lmtPriceOffset = op.lmtPriceOffset
+ if (op.adjustedStopPrice !== undefined) order.adjustedStopPrice = op.adjustedStopPrice
+ if (op.adjustedStopLimitPrice !== undefined) order.adjustedStopLimitPrice = op.adjustedStopLimitPrice
+ if (op.adjustedTrailingAmount !== undefined) order.adjustedTrailingAmount = op.adjustedTrailingAmount
+ if (op.adjustableTrailingUnit !== undefined) order.adjustableTrailingUnit = op.adjustableTrailingUnit
+
+ // soft dollar tier
+ const sdt = decodeSoftDollarTierFromProto(op)
+ if (sdt) order.softDollarTier = sdt
+
+ if (op.cashQty !== undefined) order.cashQty = op.cashQty
+ if (op.dontUseAutoPriceForHedge !== undefined) order.dontUseAutoPriceForHedge = op.dontUseAutoPriceForHedge
+ if (op.isOmsContainer !== undefined) order.isOmsContainer = op.isOmsContainer
+ if (op.discretionaryUpToLimitPrice !== undefined) order.discretionaryUpToLimitPrice = op.discretionaryUpToLimitPrice
+ if (op.usePriceMgmtAlgo !== undefined) order.usePriceMgmtAlgo = op.usePriceMgmtAlgo !== 0 ? true : false
+ if (op.duration !== undefined) order.duration = op.duration
+ if (op.postToAts !== undefined) order.postToAts = op.postToAts
+ if (op.autoCancelParent !== undefined) order.autoCancelParent = op.autoCancelParent
+ if (op.minTradeQty !== undefined) order.minTradeQty = op.minTradeQty
+ if (op.minCompeteSize !== undefined) order.minCompeteSize = op.minCompeteSize
+ if (op.competeAgainstBestOffset !== undefined) order.competeAgainstBestOffset = op.competeAgainstBestOffset
+ if (op.midOffsetAtWhole !== undefined) order.midOffsetAtWhole = op.midOffsetAtWhole
+ if (op.midOffsetAtHalf !== undefined) order.midOffsetAtHalf = op.midOffsetAtHalf
+ if (op.customerAccount !== undefined) order.customerAccount = op.customerAccount
+ if (op.professionalCustomer !== undefined) order.professionalCustomer = op.professionalCustomer
+ if (op.bondAccruedInterest !== undefined) order.bondAccruedInterest = op.bondAccruedInterest
+ if (op.includeOvernight !== undefined) order.includeOvernight = op.includeOvernight
+ if (op.extOperator !== undefined) order.extOperator = op.extOperator
+ if (op.manualOrderIndicator !== undefined) order.manualOrderIndicator = op.manualOrderIndicator
+ if (op.submitter !== undefined) order.submitter = op.submitter
+ if (op.imbalanceOnly !== undefined) order.imbalanceOnly = op.imbalanceOnly
+ if (op.autoCancelDate !== undefined) order.autoCancelDate = op.autoCancelDate
+ if (op.filledQuantity !== undefined) order.filledQuantity = new Decimal(op.filledQuantity)
+ if (op.refFuturesConId !== undefined) order.refFuturesConId = op.refFuturesConId
+ if (op.shareholder !== undefined) order.shareholder = op.shareholder
+ if (op.routeMarketableToBbo !== undefined) order.routeMarketableToBbo = op.routeMarketableToBbo !== 0 ? true : false
+ if (op.parentPermId !== undefined) order.parentPermId = op.parentPermId
+ if (op.postOnly !== undefined) order.postOnly = op.postOnly
+ if (op.allowPreOpen !== undefined) order.allowPreOpen = op.allowPreOpen
+ if (op.ignoreOpenAuction !== undefined) order.ignoreOpenAuction = op.ignoreOpenAuction
+ if (op.deactivate !== undefined) order.deactivate = op.deactivate
+ if (op.activeStartTime !== undefined) order.activeStartTime = op.activeStartTime
+ if (op.activeStopTime !== undefined) order.activeStopTime = op.activeStopTime
+ if (op.seekPriceImprovement !== undefined) order.seekPriceImprovement = op.seekPriceImprovement !== 0 ? true : false
+ if (op.whatIfType !== undefined) order.whatIfType = op.whatIfType
+
+ return order
+}
+
+function decodeOrderStateFromProto(osp: OrderStateProto): OrderState {
+ const os = new OrderState()
+ if (osp.status !== undefined) os.status = osp.status
+ if (osp.initMarginBefore !== undefined) os.initMarginBefore = decimalMaxString(new Decimal(osp.initMarginBefore))
+ if (osp.maintMarginBefore !== undefined) os.maintMarginBefore = decimalMaxString(new Decimal(osp.maintMarginBefore))
+ if (osp.equityWithLoanBefore !== undefined) os.equityWithLoanBefore = decimalMaxString(new Decimal(osp.equityWithLoanBefore))
+ if (osp.initMarginChange !== undefined) os.initMarginChange = decimalMaxString(new Decimal(osp.initMarginChange))
+ if (osp.maintMarginChange !== undefined) os.maintMarginChange = decimalMaxString(new Decimal(osp.maintMarginChange))
+ if (osp.equityWithLoanChange !== undefined) os.equityWithLoanChange = decimalMaxString(new Decimal(osp.equityWithLoanChange))
+ if (osp.initMarginAfter !== undefined) os.initMarginAfter = decimalMaxString(new Decimal(osp.initMarginAfter))
+ if (osp.maintMarginAfter !== undefined) os.maintMarginAfter = decimalMaxString(new Decimal(osp.maintMarginAfter))
+ if (osp.equityWithLoanAfter !== undefined) os.equityWithLoanAfter = decimalMaxString(new Decimal(osp.equityWithLoanAfter))
+ if (osp.commissionAndFees !== undefined) os.commissionAndFees = osp.commissionAndFees
+ if (osp.minCommissionAndFees !== undefined) os.minCommissionAndFees = osp.minCommissionAndFees
+ if (osp.maxCommissionAndFees !== undefined) os.maxCommissionAndFees = osp.maxCommissionAndFees
+ if (osp.commissionAndFeesCurrency !== undefined) os.commissionAndFeesCurrency = osp.commissionAndFeesCurrency
+ if (osp.warningText !== undefined) os.warningText = osp.warningText
+ if (osp.marginCurrency !== undefined) os.marginCurrency = osp.marginCurrency
+ if (osp.initMarginBeforeOutsideRTH !== undefined) os.initMarginBeforeOutsideRTH = osp.initMarginBeforeOutsideRTH
+ if (osp.maintMarginBeforeOutsideRTH !== undefined) os.maintMarginBeforeOutsideRTH = osp.maintMarginBeforeOutsideRTH
+ if (osp.equityWithLoanBeforeOutsideRTH !== undefined) os.equityWithLoanBeforeOutsideRTH = osp.equityWithLoanBeforeOutsideRTH
+ if (osp.initMarginChangeOutsideRTH !== undefined) os.initMarginChangeOutsideRTH = osp.initMarginChangeOutsideRTH
+ if (osp.maintMarginChangeOutsideRTH !== undefined) os.maintMarginChangeOutsideRTH = osp.maintMarginChangeOutsideRTH
+ if (osp.equityWithLoanChangeOutsideRTH !== undefined) os.equityWithLoanChangeOutsideRTH = osp.equityWithLoanChangeOutsideRTH
+ if (osp.initMarginAfterOutsideRTH !== undefined) os.initMarginAfterOutsideRTH = osp.initMarginAfterOutsideRTH
+ if (osp.maintMarginAfterOutsideRTH !== undefined) os.maintMarginAfterOutsideRTH = osp.maintMarginAfterOutsideRTH
+ if (osp.equityWithLoanAfterOutsideRTH !== undefined) os.equityWithLoanAfterOutsideRTH = osp.equityWithLoanAfterOutsideRTH
+ if (osp.suggestedSize !== undefined) os.suggestedSize = new Decimal(osp.suggestedSize)
+ if (osp.rejectReason !== undefined) os.rejectReason = osp.rejectReason
+
+ // order allocations
+ if (osp.orderAllocations && osp.orderAllocations.length > 0) {
+ const allocs: OrderAllocation[] = []
+ for (const oap of osp.orderAllocations) {
+ const oa = new OrderAllocation()
+ if (oap.account !== undefined) oa.account = oap.account
+ if (oap.position !== undefined) oa.position = new Decimal(oap.position)
+ if (oap.positionDesired !== undefined) oa.positionDesired = new Decimal(oap.positionDesired)
+ if (oap.positionAfter !== undefined) oa.positionAfter = new Decimal(oap.positionAfter)
+ if (oap.desiredAllocQty !== undefined) oa.desiredAllocQty = new Decimal(oap.desiredAllocQty)
+ if (oap.allowedAllocQty !== undefined) oa.allowedAllocQty = new Decimal(oap.allowedAllocQty)
+ if (oap.isMonetary !== undefined) oa.isMonetary = oap.isMonetary
+ allocs.push(oa)
+ }
+ os.orderAllocations = allocs
+ }
+
+ if (osp.completedTime !== undefined) os.completedTime = osp.completedTime
+ if (osp.completedStatus !== undefined) os.completedStatus = osp.completedStatus
+
+ return os
+}
+
+// ---------------------------------------------------------------------------
+// Apply handlers
+// ---------------------------------------------------------------------------
+
+export function applyOrderHandlers(decoder: Decoder): void {
+ // -----------------------------------------------------------------------
+ // IN.ORDER_STATUS (3) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.ORDER_STATUS, (d, fields) => {
+ decodeInt(fields) // msgId
+ if (d.serverVersion < MIN_SERVER_VER_MARKET_CAP_PRICE) {
+ decodeInt(fields) // version
+ }
+ const orderId = decodeInt(fields)
+ const status = decodeStr(fields)
+ const filled = decodeDecimal(fields)
+ const remaining = decodeDecimal(fields)
+ const avgFillPrice = decodeFloat(fields)
+
+ const permId = decodeInt(fields) // ver 2
+ const parentId = decodeInt(fields) // ver 3
+ const lastFillPrice = decodeFloat(fields) // ver 4
+ const clientId = decodeInt(fields) // ver 5
+ const whyHeld = decodeStr(fields) // ver 6
+
+ let mktCapPrice = 0
+ if (d.serverVersion >= MIN_SERVER_VER_MARKET_CAP_PRICE) {
+ mktCapPrice = decodeFloat(fields)
+ }
+
+ d.wrapper.orderStatus(
+ orderId, status, filled, remaining, avgFillPrice,
+ permId, parentId, lastFillPrice, clientId, whyHeld,
+ mktCapPrice,
+ )
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.ORDER_STATUS (3) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.ORDER_STATUS, (d, buf) => {
+ const proto = OrderStatusProto.decode(buf)
+
+ const orderId = proto.orderId ?? UNSET_INTEGER
+ const status = proto.status ?? ''
+ const filled = proto.filled !== undefined
+ ? new Decimal(proto.filled)
+ : UNSET_DECIMAL
+ const remaining = proto.remaining !== undefined
+ ? new Decimal(proto.remaining)
+ : UNSET_DECIMAL
+ const avgFillPrice = proto.avgFillPrice ?? UNSET_DOUBLE
+ const permId = proto.permId ?? UNSET_INTEGER
+ const parentId = proto.parentId ?? UNSET_INTEGER
+ const lastFillPrice = proto.lastFillPrice ?? UNSET_DOUBLE
+ const clientId = proto.clientId ?? UNSET_INTEGER
+ const whyHeld = proto.whyHeld ?? ''
+ const mktCapPrice = proto.mktCapPrice ?? UNSET_DOUBLE
+
+ d.wrapper.orderStatus(
+ orderId, status, filled, remaining, avgFillPrice,
+ permId, parentId, lastFillPrice, clientId, whyHeld,
+ mktCapPrice,
+ )
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.OPEN_ORDER (5) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.OPEN_ORDER, (d, fields) => {
+ decodeInt(fields) // msgId
+
+ const order = new Order()
+ const contract = new Contract()
+ const orderState = new OrderState()
+
+ let version: number
+ if (d.serverVersion < MIN_SERVER_VER_ORDER_CONTAINER) {
+ version = decodeInt(fields)
+ } else {
+ version = d.serverVersion
+ }
+
+ const od = new OrderDecoder(contract, order, orderState, version, d.serverVersion)
+
+ od.decodeOrderId(fields)
+ od.decodeContractFields(fields)
+ od.decodeAction(fields)
+ od.decodeTotalQuantity(fields)
+ od.decodeOrderType(fields)
+ od.decodeLmtPrice(fields)
+ od.decodeAuxPrice(fields)
+ od.decodeTIF(fields)
+ od.decodeOcaGroup(fields)
+ od.decodeAccount(fields)
+ od.decodeOpenClose(fields)
+ od.decodeOrigin(fields)
+ od.decodeOrderRef(fields)
+ od.decodeClientId(fields)
+ od.decodePermId(fields)
+ od.decodeOutsideRth(fields)
+ od.decodeHidden(fields)
+ od.decodeDiscretionaryAmt(fields)
+ od.decodeGoodAfterTime(fields)
+ od.skipSharesAllocation(fields)
+ od.decodeFAParams(fields)
+ od.decodeModelCode(fields)
+ od.decodeGoodTillDate(fields)
+ od.decodeRule80A(fields)
+ od.decodePercentOffset(fields)
+ od.decodeSettlingFirm(fields)
+ od.decodeShortSaleParams(fields)
+ od.decodeAuctionStrategy(fields)
+ od.decodeBoxOrderParams(fields)
+ od.decodePegToStkOrVolOrderParams(fields)
+ od.decodeDisplaySize(fields)
+ od.decodeBlockOrder(fields)
+ od.decodeSweepToFill(fields)
+ od.decodeAllOrNone(fields)
+ od.decodeMinQty(fields)
+ od.decodeOcaType(fields)
+ od.skipETradeOnly(fields)
+ od.skipFirmQuoteOnly(fields)
+ od.skipNbboPriceCap(fields)
+ od.decodeParentId(fields)
+ od.decodeTriggerMethod(fields)
+ od.decodeVolOrderParams(fields, true)
+ od.decodeTrailParams(fields)
+ od.decodeBasisPoints(fields)
+ od.decodeComboLegs(fields)
+ od.decodeSmartComboRoutingParams(fields)
+ od.decodeScaleOrderParams(fields)
+ od.decodeHedgeParams(fields)
+ od.decodeOptOutSmartRouting(fields)
+ od.decodeClearingParams(fields)
+ od.decodeNotHeld(fields)
+ od.decodeDeltaNeutral(fields)
+ od.decodeAlgoParams(fields)
+ od.decodeSolicited(fields)
+ od.decodeWhatIfInfoAndCommissionAndFees(fields)
+ od.decodeVolRandomizeFlags(fields)
+ od.decodePegToBenchParams(fields)
+ od.decodeConditions(fields)
+ od.decodeAdjustedOrderParams(fields)
+ od.decodeSoftDollarTier(fields)
+ od.decodeCashQty(fields)
+ od.decodeDontUseAutoPriceForHedge(fields)
+ od.decodeIsOmsContainers(fields)
+ od.decodeDiscretionaryUpToLimitPrice(fields)
+ od.decodeUsePriceMgmtAlgo(fields)
+ od.decodeDuration(fields)
+ od.decodePostToAts(fields)
+ od.decodeAutoCancelParent(fields, MIN_SERVER_VER_AUTO_CANCEL_PARENT)
+ od.decodePegBestPegMidOrderAttributes(fields)
+ od.decodeCustomerAccount(fields)
+ od.decodeProfessionalCustomer(fields)
+ od.decodeBondAccruedInterest(fields)
+ od.decodeIncludeOvernight(fields)
+ od.decodeCMETaggingFields(fields)
+ od.decodeSubmitter(fields)
+ od.decodeImbalanceOnly(fields, MIN_SERVER_VER_IMBALANCE_ONLY)
+
+ d.wrapper.openOrder(order.orderId, contract, order, orderState)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.OPEN_ORDER (5) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.OPEN_ORDER, (d, buf) => {
+ const proto = OpenOrderProto.decode(buf)
+
+ const orderId = proto.orderId ?? 0
+
+ // decode contract fields
+ if (!proto.contract) return
+ const contract = decodeContractFromProto(proto.contract)
+
+ // decode order fields
+ if (!proto.order) return
+ const order = decodeOrderFromProto(orderId, proto.contract, proto.order)
+
+ // decode order state fields
+ if (!proto.orderState) return
+ const orderState = decodeOrderStateFromProto(proto.orderState)
+
+ d.wrapper.openOrder(orderId, contract, order, orderState)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.OPEN_ORDER_END (53) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.OPEN_ORDER_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ d.wrapper.openOrderEnd()
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.OPEN_ORDER_END (53) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.OPEN_ORDER_END, (d, buf) => {
+ OpenOrdersEndProto.decode(buf)
+ d.wrapper.openOrderEnd()
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.ORDER_BOUND (100) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.ORDER_BOUND, (d, fields) => {
+ decodeInt(fields) // msgId
+ const permId = decodeInt(fields)
+ const clientId = decodeInt(fields)
+ const orderId = decodeInt(fields)
+
+ d.wrapper.orderBound(permId, clientId, orderId)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.ORDER_BOUND (100) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.ORDER_BOUND, (d, buf) => {
+ const proto = OrderBoundProto.decode(buf)
+
+ const permId = proto.permId ?? UNSET_INTEGER
+ const clientId = proto.clientId ?? UNSET_INTEGER
+ const orderId = proto.orderId ?? UNSET_INTEGER
+
+ d.wrapper.orderBound(permId, clientId, orderId)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.COMPLETED_ORDER (101) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.COMPLETED_ORDER, (d, fields) => {
+ decodeInt(fields) // msgId
+
+ const order = new Order()
+ const contract = new Contract()
+ const orderState = new OrderState()
+
+ const od = new OrderDecoder(contract, order, orderState, UNSET_INTEGER, d.serverVersion)
+
+ od.decodeContractFields(fields)
+ od.decodeAction(fields)
+ od.decodeTotalQuantity(fields)
+ od.decodeOrderType(fields)
+ od.decodeLmtPrice(fields)
+ od.decodeAuxPrice(fields)
+ od.decodeTIF(fields)
+ od.decodeOcaGroup(fields)
+ od.decodeAccount(fields)
+ od.decodeOpenClose(fields)
+ od.decodeOrigin(fields)
+ od.decodeOrderRef(fields)
+ od.decodePermId(fields)
+ od.decodeOutsideRth(fields)
+ od.decodeHidden(fields)
+ od.decodeDiscretionaryAmt(fields)
+ od.decodeGoodAfterTime(fields)
+ od.decodeFAParams(fields)
+ od.decodeModelCode(fields)
+ od.decodeGoodTillDate(fields)
+ od.decodeRule80A(fields)
+ od.decodePercentOffset(fields)
+ od.decodeSettlingFirm(fields)
+ od.decodeShortSaleParams(fields)
+ od.decodeBoxOrderParams(fields)
+ od.decodePegToStkOrVolOrderParams(fields)
+ od.decodeDisplaySize(fields)
+ od.decodeSweepToFill(fields)
+ od.decodeAllOrNone(fields)
+ od.decodeMinQty(fields)
+ od.decodeOcaType(fields)
+ od.decodeTriggerMethod(fields)
+ od.decodeVolOrderParams(fields, false)
+ od.decodeTrailParams(fields)
+ od.decodeComboLegs(fields)
+ od.decodeSmartComboRoutingParams(fields)
+ od.decodeScaleOrderParams(fields)
+ od.decodeHedgeParams(fields)
+ od.decodeClearingParams(fields)
+ od.decodeNotHeld(fields)
+ od.decodeDeltaNeutral(fields)
+ od.decodeAlgoParams(fields)
+ od.decodeSolicited(fields)
+ od.decodeOrderStatus(fields)
+ od.decodeVolRandomizeFlags(fields)
+ od.decodePegToBenchParams(fields)
+ od.decodeConditions(fields)
+ od.decodeStopPriceAndLmtPriceOffset(fields)
+ od.decodeCashQty(fields)
+ od.decodeDontUseAutoPriceForHedge(fields)
+ od.decodeIsOmsContainers(fields)
+ od.decodeAutoCancelDate(fields)
+ od.decodeFilledQuantity(fields)
+ od.decodeRefFuturesConId(fields)
+ od.decodeAutoCancelParent(fields)
+ od.decodeShareholder(fields)
+ od.decodeImbalanceOnly(fields)
+ od.decodeRouteMarketableToBbo(fields)
+ od.decodeParentPermId(fields)
+ od.decodeCompletedTime(fields)
+ od.decodeCompletedStatus(fields)
+ od.decodePegBestPegMidOrderAttributes(fields)
+ od.decodeCustomerAccount(fields)
+ od.decodeProfessionalCustomer(fields)
+ od.decodeSubmitter(fields)
+
+ d.wrapper.completedOrder(contract, order, orderState)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.COMPLETED_ORDER (101) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.COMPLETED_ORDER, (d, buf) => {
+ const proto = CompletedOrderProto.decode(buf)
+
+ // decode contract fields
+ if (!proto.contract) return
+ const contract = decodeContractFromProto(proto.contract)
+
+ // decode order fields
+ if (!proto.order) return
+ const order = decodeOrderFromProto(UNSET_INTEGER, proto.contract, proto.order)
+
+ // decode order state fields
+ if (!proto.orderState) return
+ const orderState = decodeOrderStateFromProto(proto.orderState)
+
+ d.wrapper.completedOrder(contract, order, orderState)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.COMPLETED_ORDERS_END (102) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.COMPLETED_ORDERS_END, (d, fields) => {
+ decodeInt(fields) // msgId
+ d.wrapper.completedOrdersEnd()
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.COMPLETED_ORDERS_END (102) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.COMPLETED_ORDERS_END, (d, buf) => {
+ CompletedOrdersEndProto.decode(buf)
+ d.wrapper.completedOrdersEnd()
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.NEXT_VALID_ID (9) — text
+ // -----------------------------------------------------------------------
+ decoder.registerText(IN.NEXT_VALID_ID, (d, fields) => {
+ decodeInt(fields) // msgId
+ decodeInt(fields) // version
+ const orderId = decodeInt(fields)
+ d.wrapper.nextValidId(orderId)
+ })
+
+ // -----------------------------------------------------------------------
+ // IN.NEXT_VALID_ID (9) — protobuf
+ // -----------------------------------------------------------------------
+ decoder.registerProto(IN.NEXT_VALID_ID, (d, buf) => {
+ const proto = NextValidIdProto.decode(buf)
+ d.wrapper.nextValidId(proto.orderId ?? 0)
+ })
+}
+
diff --git a/packages/ibkr/src/errors.ts b/packages/ibkr/src/errors.ts
new file mode 100644
index 00000000..47638d22
--- /dev/null
+++ b/packages/ibkr/src/errors.ts
@@ -0,0 +1,116 @@
+/**
+ * TWS API error codes and messages.
+ * Mirrors: ibapi/errors.py
+ */
+
+export class CodeMsgPair {
+ constructor(
+ public readonly errorCode: number,
+ public readonly errorMsg: string,
+ ) {}
+
+ code(): number {
+ return this.errorCode
+ }
+
+ msg(): string {
+ return this.errorMsg
+ }
+}
+
+export const ALREADY_CONNECTED = new CodeMsgPair(501, 'Already connected.')
+export const CONNECT_FAIL = new CodeMsgPair(
+ 502,
+ `Couldn't connect to TWS. Confirm that "Enable ActiveX and Socket Clients" ` +
+ `is enabled and connection port is the same as "Socket Port" on the ` +
+ `TWS "Edit->Global Configuration...->API->Settings" menu. Live Trading ports: ` +
+ `TWS: 7496; IB Gateway: 4001. Simulated Trading ports: TWS: 7497; IB Gateway: 4002. ` +
+ `Verify that the maximum API connection threshold (default 32) is not exceeded.`,
+)
+export const UPDATE_TWS = new CodeMsgPair(503, 'The TWS is out of date and must be upgraded.')
+export const NOT_CONNECTED = new CodeMsgPair(504, 'Not connected')
+export const UNKNOWN_ID = new CodeMsgPair(505, 'Fatal Error: Unknown message id.')
+export const BAD_LENGTH = new CodeMsgPair(507, 'Bad message length')
+export const BAD_MESSAGE = new CodeMsgPair(508, 'Bad message')
+export const FAIL_SEND_REQMKT = new CodeMsgPair(510, 'Request Market Data Sending Error - ')
+export const FAIL_SEND_CANMKT = new CodeMsgPair(511, 'Cancel Market Data Sending Error - ')
+export const FAIL_SEND_ORDER = new CodeMsgPair(512, 'Order Sending Error - ')
+export const FAIL_SEND_ACCT = new CodeMsgPair(513, 'Account Update Request Sending Error - ')
+export const FAIL_SEND_EXEC = new CodeMsgPair(514, 'Request For Executions Sending Error - ')
+export const FAIL_SEND_CORDER = new CodeMsgPair(515, 'Cancel Order Sending Error - ')
+export const FAIL_SEND_OORDER = new CodeMsgPair(516, 'Request Open Order Sending Error - ')
+export const FAIL_SEND_REQCONTRACT = new CodeMsgPair(518, 'Request Contract Data Sending Error - ')
+export const FAIL_SEND_REQMKTDEPTH = new CodeMsgPair(519, 'Request Market Depth Sending Error - ')
+export const FAIL_CREATE_SOCK = new CodeMsgPair(520, 'Failed to create socket')
+export const FAIL_SEND_SERVER_LOG_LEVEL = new CodeMsgPair(521, 'Set Server Log Level Sending Error - ')
+export const FAIL_SEND_FA_REQUEST = new CodeMsgPair(522, 'FA Information Request Sending Error - ')
+export const FAIL_SEND_FA_REPLACE = new CodeMsgPair(523, 'FA Information Replace Sending Error - ')
+export const FAIL_SEND_REQSCANNER = new CodeMsgPair(524, 'Request Scanner Subscription Sending Error - ')
+export const FAIL_SEND_CANSCANNER = new CodeMsgPair(525, 'Cancel Scanner Subscription Sending Error - ')
+export const FAIL_SEND_REQSCANNERPARAMETERS = new CodeMsgPair(526, 'Request Scanner Parameter Sending Error - ')
+export const FAIL_SEND_REQHISTDATA = new CodeMsgPair(527, 'Request Historical Data Sending Error - ')
+export const FAIL_SEND_CANHISTDATA = new CodeMsgPair(528, 'Request Historical Data Sending Error - ')
+export const FAIL_SEND_REQRTBARS = new CodeMsgPair(529, 'Request Real-time Bar Data Sending Error - ')
+export const FAIL_SEND_CANRTBARS = new CodeMsgPair(530, 'Cancel Real-time Bar Data Sending Error - ')
+export const FAIL_SEND_REQCURRTIME = new CodeMsgPair(531, 'Request Current Time Sending Error - ')
+export const FAIL_SEND_REQFUNDDATA = new CodeMsgPair(532, 'Request Fundamental Data Sending Error - ')
+export const FAIL_SEND_CANFUNDDATA = new CodeMsgPair(533, 'Cancel Fundamental Data Sending Error - ')
+export const FAIL_SEND_REQCALCIMPLIEDVOLAT = new CodeMsgPair(534, 'Request Calculate Implied Volatility Sending Error - ')
+export const FAIL_SEND_REQCALCOPTIONPRICE = new CodeMsgPair(535, 'Request Calculate Option Price Sending Error - ')
+export const FAIL_SEND_CANCALCIMPLIEDVOLAT = new CodeMsgPair(536, 'Cancel Calculate Implied Volatility Sending Error - ')
+export const FAIL_SEND_CANCALCOPTIONPRICE = new CodeMsgPair(537, 'Cancel Calculate Option Price Sending Error - ')
+export const FAIL_SEND_REQGLOBALCANCEL = new CodeMsgPair(538, 'Request Global Cancel Sending Error - ')
+export const FAIL_SEND_REQMARKETDATATYPE = new CodeMsgPair(539, 'Request Market Data Type Sending Error - ')
+export const FAIL_SEND_REQPOSITIONS = new CodeMsgPair(540, 'Request Positions Sending Error - ')
+export const FAIL_SEND_CANPOSITIONS = new CodeMsgPair(541, 'Cancel Positions Sending Error - ')
+export const FAIL_SEND_REQACCOUNTDATA = new CodeMsgPair(542, 'Request Account Data Sending Error - ')
+export const FAIL_SEND_CANACCOUNTDATA = new CodeMsgPair(543, 'Cancel Account Data Sending Error - ')
+export const FAIL_SEND_VERIFYREQUEST = new CodeMsgPair(544, 'Verify Request Sending Error - ')
+export const FAIL_SEND_VERIFYMESSAGE = new CodeMsgPair(545, 'Verify Message Sending Error - ')
+export const FAIL_SEND_QUERYDISPLAYGROUPS = new CodeMsgPair(546, 'Query Display Groups Sending Error - ')
+export const FAIL_SEND_SUBSCRIBETOGROUPEVENTS = new CodeMsgPair(547, 'Subscribe To Group Events Sending Error - ')
+export const FAIL_SEND_UPDATEDISPLAYGROUP = new CodeMsgPair(548, 'Update Display Group Sending Error - ')
+export const FAIL_SEND_UNSUBSCRIBEFROMGROUPEVENTS = new CodeMsgPair(549, 'Unsubscribe From Group Events Sending Error - ')
+export const FAIL_SEND_STARTAPI = new CodeMsgPair(550, 'Start API Sending Error - ')
+export const FAIL_SEND_VERIFYANDAUTHREQUEST = new CodeMsgPair(551, 'Verify And Auth Request Sending Error - ')
+export const FAIL_SEND_VERIFYANDAUTHMESSAGE = new CodeMsgPair(552, 'Verify And Auth Message Sending Error - ')
+export const FAIL_SEND_REQPOSITIONSMULTI = new CodeMsgPair(553, 'Request Positions Multi Sending Error - ')
+export const FAIL_SEND_CANPOSITIONSMULTI = new CodeMsgPair(554, 'Cancel Positions Multi Sending Error - ')
+export const FAIL_SEND_REQACCOUNTUPDATESMULTI = new CodeMsgPair(555, 'Request Account Updates Multi Sending Error - ')
+export const FAIL_SEND_CANACCOUNTUPDATESMULTI = new CodeMsgPair(556, 'Cancel Account Updates Multi Sending Error - ')
+export const FAIL_SEND_REQSECDEFOPTPARAMS = new CodeMsgPair(557, 'Request Security Definition Option Params Sending Error - ')
+export const FAIL_SEND_REQSOFTDOLLARTIERS = new CodeMsgPair(558, 'Request Soft Dollar Tiers Sending Error - ')
+export const FAIL_SEND_REQFAMILYCODES = new CodeMsgPair(559, 'Request Family Codes Sending Error - ')
+export const FAIL_SEND_REQMATCHINGSYMBOLS = new CodeMsgPair(560, 'Request Matching Symbols Sending Error - ')
+export const FAIL_SEND_REQMKTDEPTHEXCHANGES = new CodeMsgPair(561, 'Request Market Depth Exchanges Sending Error - ')
+export const FAIL_SEND_REQSMARTCOMPONENTS = new CodeMsgPair(562, 'Request Smart Components Sending Error - ')
+export const FAIL_SEND_REQNEWSPROVIDERS = new CodeMsgPair(563, 'Request News Providers Sending Error - ')
+export const FAIL_SEND_REQNEWSARTICLE = new CodeMsgPair(564, 'Request News Article Sending Error - ')
+export const FAIL_SEND_REQHISTORICALNEWS = new CodeMsgPair(565, 'Request Historical News Sending Error - ')
+export const FAIL_SEND_REQHEADTIMESTAMP = new CodeMsgPair(566, 'Request Head Time Stamp Sending Error - ')
+export const FAIL_SEND_REQHISTOGRAMDATA = new CodeMsgPair(567, 'Request Histogram Data Sending Error - ')
+export const FAIL_SEND_CANCELHISTOGRAMDATA = new CodeMsgPair(568, 'Cancel Request Histogram Data Sending Error - ')
+export const FAIL_SEND_CANCELHEADTIMESTAMP = new CodeMsgPair(569, 'Cancel Head Time Stamp Sending Error - ')
+export const FAIL_SEND_REQMARKETRULE = new CodeMsgPair(570, 'Request Market Rule Sending Error - ')
+export const FAIL_SEND_REQPNL = new CodeMsgPair(571, 'Request PnL Sending Error - ')
+export const FAIL_SEND_CANCELPNL = new CodeMsgPair(572, 'Cancel PnL Sending Error - ')
+export const FAIL_SEND_REQPNLSINGLE = new CodeMsgPair(573, 'Request PnL Single Error - ')
+export const FAIL_SEND_CANCELPNLSINGLE = new CodeMsgPair(574, 'Cancel PnL Single Sending Error - ')
+export const FAIL_SEND_REQHISTORICALTICKS = new CodeMsgPair(575, 'Request Historical Ticks Error - ')
+export const FAIL_SEND_REQTICKBYTICKDATA = new CodeMsgPair(576, 'Request Tick-By-Tick Data Sending Error - ')
+export const FAIL_SEND_CANCELTICKBYTICKDATA = new CodeMsgPair(577, 'Cancel Tick-By-Tick Data Sending Error - ')
+export const FAIL_SEND_REQCOMPLETEDORDERS = new CodeMsgPair(578, 'Request Completed Orders Sending Error - ')
+export const INVALID_SYMBOL = new CodeMsgPair(579, 'Invalid symbol in string - ')
+export const FAIL_SEND_REQ_WSH_META_DATA = new CodeMsgPair(580, 'Request WSH Meta Data Sending Error - ')
+export const FAIL_SEND_CAN_WSH_META_DATA = new CodeMsgPair(581, 'Cancel WSH Meta Data Sending Error - ')
+export const FAIL_SEND_REQ_WSH_EVENT_DATA = new CodeMsgPair(582, 'Request WSH Event Data Sending Error - ')
+export const FAIL_SEND_CAN_WSH_EVENT_DATA = new CodeMsgPair(583, 'Cancel WSH Event Data Sending Error - ')
+export const FAIL_SEND_REQ_USER_INFO = new CodeMsgPair(584, 'Request User Info Sending Error - ')
+export const FA_PROFILE_NOT_SUPPORTED = new CodeMsgPair(585, 'FA Profile is not supported anymore, use FA Group instead - ')
+export const FAIL_SEND_REQCURRTIMEINMILLIS = new CodeMsgPair(587, 'Request Current Time In Millis Sending Error - ')
+export const ERROR_ENCODING_PROTOBUF = new CodeMsgPair(588, 'Error encoding protobuf - ')
+export const FAIL_SEND_CANMKTDEPTH = new CodeMsgPair(589, 'Cancel Market Depth Sending Error - ')
+export const FAIL_SEND_CANCEL_CONTRACT_DATA = new CodeMsgPair(590, 'Cancel Contract Data Sending Error - ')
+export const FAIL_SEND_CANCEL_HISTORICAL_TICKS = new CodeMsgPair(591, 'Cancel Historical Ticks Sending Error - ')
+export const FAIL_SEND_REQCONFIG = new CodeMsgPair(592, 'Request Config Sending Error - ')
+export const FAIL_SEND_UPDATECONFIG = new CodeMsgPair(593, 'Update Config Request Sending Error - ')
diff --git a/packages/ibkr/src/execution.ts b/packages/ibkr/src/execution.ts
new file mode 100644
index 00000000..35bde64d
--- /dev/null
+++ b/packages/ibkr/src/execution.ts
@@ -0,0 +1,94 @@
+/**
+ * Mirrors: ibapi/execution.py
+ */
+
+import Decimal from 'decimal.js'
+import { UNSET_DECIMAL, UNSET_INTEGER } from './const.js'
+
+function floatMaxString(val: number): string {
+ return val === Number.MAX_VALUE ? '' : String(val)
+}
+
+function decimalMaxString(val: Decimal): string {
+ return val.eq(UNSET_DECIMAL) ? '' : val.toString()
+}
+
+function intMaxString(val: number): string {
+ return val === UNSET_INTEGER ? '' : String(val)
+}
+
+function longMaxString(val: number): string {
+ return val === UNSET_INTEGER ? '' : String(val)
+}
+
+export const OptionExerciseType = {
+ NoneItem: { value: -1, label: 'None' },
+ Exercise: { value: 1, label: 'Exercise' },
+ Lapse: { value: 2, label: 'Lapse' },
+ DoNothing: { value: 3, label: 'DoNothing' },
+ Assigned: { value: 100, label: 'Assigned ' },
+ AutoexerciseClearing: { value: 101, label: 'AutoexerciseClearing' },
+ Expired: { value: 102, label: 'Expired' },
+ Netting: { value: 103, label: 'Netting' },
+ AutoexerciseTrading: { value: 200, label: 'AutoexerciseTrading' },
+} as const
+
+export type OptionExerciseTypeEntry = (typeof OptionExerciseType)[keyof typeof OptionExerciseType]
+
+function getOptionExerciseTypeName(entry: OptionExerciseTypeEntry): string {
+ for (const [key, val] of Object.entries(OptionExerciseType)) {
+ if (val === entry) return key
+ }
+ return 'Unknown'
+}
+
+export class Execution {
+ execId = ''
+ time = ''
+ acctNumber = ''
+ exchange = ''
+ side = ''
+ shares: Decimal = UNSET_DECIMAL
+ price = 0.0
+ permId = 0
+ clientId = 0
+ orderId = 0
+ liquidation = 0
+ cumQty: Decimal = UNSET_DECIMAL
+ avgPrice = 0.0
+ orderRef = ''
+ evRule = ''
+ evMultiplier = 0.0
+ modelCode = ''
+ lastLiquidity = 0
+ pendingPriceRevision = false
+ submitter = ''
+ optExerciseOrLapseType: OptionExerciseTypeEntry = OptionExerciseType.NoneItem
+
+ toString(): string {
+ return (
+ `ExecId: ${this.execId}, Time: ${this.time}, Account: ${this.acctNumber}, ` +
+ `Exchange: ${this.exchange}, Side: ${this.side}, Shares: ${decimalMaxString(this.shares)}, ` +
+ `Price: ${floatMaxString(this.price)}, PermId: ${longMaxString(this.permId)}, ` +
+ `ClientId: ${intMaxString(this.clientId)}, OrderId: ${intMaxString(this.orderId)}, ` +
+ `Liquidation: ${intMaxString(this.liquidation)}, CumQty: ${decimalMaxString(this.cumQty)}, ` +
+ `AvgPrice: ${floatMaxString(this.avgPrice)}, OrderRef: ${this.orderRef}, ` +
+ `EvRule: ${this.evRule}, EvMultiplier: ${floatMaxString(this.evMultiplier)}, ` +
+ `ModelCode: ${this.modelCode}, LastLiquidity: ${intMaxString(this.lastLiquidity)}, ` +
+ `PendingPriceRevision: ${this.pendingPriceRevision}, Submitter: ${this.submitter}, ` +
+ `OptExerciseOrLapseType: ${getOptionExerciseTypeName(this.optExerciseOrLapseType)}`
+ )
+ }
+}
+
+export class ExecutionFilter {
+ clientId = 0
+ acctCode = ''
+ time = ''
+ symbol = ''
+ secType = ''
+ exchange = ''
+ side = ''
+ lastNDays: number = UNSET_INTEGER
+ specificDates: string[] | null = null
+}
diff --git a/packages/ibkr/src/index.ts b/packages/ibkr/src/index.ts
new file mode 100644
index 00000000..f095099f
--- /dev/null
+++ b/packages/ibkr/src/index.ts
@@ -0,0 +1,37 @@
+/**
+ * @traderalice/ibkr — TypeScript port of IBKR TWS API v10.44.01
+ */
+
+// Constants
+export * from './const.js'
+export * from './errors.js'
+export * from './server-versions.js'
+export * from './message.js'
+export * from './news.js'
+
+// Simple types
+export { TagValue, type TagValueList } from './tag-value.js'
+export { SoftDollarTier } from './softdollartier.js'
+export { type TickType, TickTypeEnum, tickTypeToString } from './tick-type.js'
+export { AccountSummaryTags, AllTags } from './account-summary-tags.js'
+export { IneligibilityReason } from './ineligibility-reason.js'
+
+// Data models
+export { Contract, ContractDetails, ComboLeg, DeltaNeutralContract, ContractDescription } from './contract.js'
+export { Order, OrderComboLeg } from './order.js'
+export { OrderState, OrderAllocation } from './order-state.js'
+export { OrderCancel } from './order-cancel.js'
+export { Execution, ExecutionFilter } from './execution.js'
+export { CommissionAndFeesReport } from './commission-and-fees-report.js'
+export { ScannerSubscription, ScanData } from './scanner.js'
+export * from './common.js'
+
+// Protocol
+export { makeField, makeFieldHandleEmpty, makeMsg, readMsg, readFields } from './comm.js'
+export { Connection } from './connection.js'
+export { EReader } from './reader.js'
+export { Decoder } from './decoder'
+
+// Client & Wrapper
+export { type EWrapper, DefaultEWrapper } from './wrapper.js'
+export { EClient } from './client/index.js'
diff --git a/packages/ibkr/src/ineligibility-reason.ts b/packages/ibkr/src/ineligibility-reason.ts
new file mode 100644
index 00000000..a39b6fd1
--- /dev/null
+++ b/packages/ibkr/src/ineligibility-reason.ts
@@ -0,0 +1,18 @@
+/**
+ * Ineligibility reason for order preview.
+ * Mirrors: ibapi/ineligibility_reason.py
+ */
+
+export class IneligibilityReason {
+ id: string
+ description: string
+
+ constructor(id?: string, description?: string) {
+ this.id = String(id ?? '')
+ this.description = String(description ?? '')
+ }
+
+ toString(): string {
+ return `[id: ${this.id}, description: ${this.description}];`
+ }
+}
diff --git a/packages/ibkr/src/message.ts b/packages/ibkr/src/message.ts
new file mode 100644
index 00000000..371f172c
--- /dev/null
+++ b/packages/ibkr/src/message.ts
@@ -0,0 +1,188 @@
+/**
+ * TWS API message type IDs — incoming and outgoing.
+ * Mirrors: ibapi/message.py
+ */
+
+// Field types (used in decoding metadata)
+export const INT = 1
+export const STR = 2
+export const FLT = 3
+
+/** Incoming message IDs (server → client) */
+export const IN = {
+ TICK_PRICE: 1,
+ TICK_SIZE: 2,
+ ORDER_STATUS: 3,
+ ERR_MSG: 4,
+ OPEN_ORDER: 5,
+ ACCT_VALUE: 6,
+ PORTFOLIO_VALUE: 7,
+ ACCT_UPDATE_TIME: 8,
+ NEXT_VALID_ID: 9,
+ CONTRACT_DATA: 10,
+ EXECUTION_DATA: 11,
+ MARKET_DEPTH: 12,
+ MARKET_DEPTH_L2: 13,
+ NEWS_BULLETINS: 14,
+ MANAGED_ACCTS: 15,
+ RECEIVE_FA: 16,
+ HISTORICAL_DATA: 17,
+ BOND_CONTRACT_DATA: 18,
+ SCANNER_PARAMETERS: 19,
+ SCANNER_DATA: 20,
+ TICK_OPTION_COMPUTATION: 21,
+ TICK_GENERIC: 45,
+ TICK_STRING: 46,
+ TICK_EFP: 47,
+ CURRENT_TIME: 49,
+ REAL_TIME_BARS: 50,
+ FUNDAMENTAL_DATA: 51,
+ CONTRACT_DATA_END: 52,
+ OPEN_ORDER_END: 53,
+ ACCT_DOWNLOAD_END: 54,
+ EXECUTION_DATA_END: 55,
+ DELTA_NEUTRAL_VALIDATION: 56,
+ TICK_SNAPSHOT_END: 57,
+ MARKET_DATA_TYPE: 58,
+ COMMISSION_AND_FEES_REPORT: 59,
+ POSITION_DATA: 61,
+ POSITION_END: 62,
+ ACCOUNT_SUMMARY: 63,
+ ACCOUNT_SUMMARY_END: 64,
+ VERIFY_MESSAGE_API: 65,
+ VERIFY_COMPLETED: 66,
+ DISPLAY_GROUP_LIST: 67,
+ DISPLAY_GROUP_UPDATED: 68,
+ VERIFY_AND_AUTH_MESSAGE_API: 69,
+ VERIFY_AND_AUTH_COMPLETED: 70,
+ POSITION_MULTI: 71,
+ POSITION_MULTI_END: 72,
+ ACCOUNT_UPDATE_MULTI: 73,
+ ACCOUNT_UPDATE_MULTI_END: 74,
+ SECURITY_DEFINITION_OPTION_PARAMETER: 75,
+ SECURITY_DEFINITION_OPTION_PARAMETER_END: 76,
+ SOFT_DOLLAR_TIERS: 77,
+ FAMILY_CODES: 78,
+ SYMBOL_SAMPLES: 79,
+ MKT_DEPTH_EXCHANGES: 80,
+ TICK_REQ_PARAMS: 81,
+ SMART_COMPONENTS: 82,
+ NEWS_ARTICLE: 83,
+ TICK_NEWS: 84,
+ NEWS_PROVIDERS: 85,
+ HISTORICAL_NEWS: 86,
+ HISTORICAL_NEWS_END: 87,
+ HEAD_TIMESTAMP: 88,
+ HISTOGRAM_DATA: 89,
+ HISTORICAL_DATA_UPDATE: 90,
+ REROUTE_MKT_DATA_REQ: 91,
+ REROUTE_MKT_DEPTH_REQ: 92,
+ MARKET_RULE: 93,
+ PNL: 94,
+ PNL_SINGLE: 95,
+ HISTORICAL_TICKS: 96,
+ HISTORICAL_TICKS_BID_ASK: 97,
+ HISTORICAL_TICKS_LAST: 98,
+ TICK_BY_TICK: 99,
+ ORDER_BOUND: 100,
+ COMPLETED_ORDER: 101,
+ COMPLETED_ORDERS_END: 102,
+ REPLACE_FA_END: 103,
+ WSH_META_DATA: 104,
+ WSH_EVENT_DATA: 105,
+ HISTORICAL_SCHEDULE: 106,
+ USER_INFO: 107,
+ HISTORICAL_DATA_END: 108,
+ CURRENT_TIME_IN_MILLIS: 109,
+ CONFIG_RESPONSE: 110,
+ UPDATE_CONFIG_RESPONSE: 111,
+} as const
+
+/** Outgoing message IDs (client → server) */
+export const OUT = {
+ REQ_MKT_DATA: 1,
+ CANCEL_MKT_DATA: 2,
+ PLACE_ORDER: 3,
+ CANCEL_ORDER: 4,
+ REQ_OPEN_ORDERS: 5,
+ REQ_ACCT_DATA: 6,
+ REQ_EXECUTIONS: 7,
+ REQ_IDS: 8,
+ REQ_CONTRACT_DATA: 9,
+ REQ_MKT_DEPTH: 10,
+ CANCEL_MKT_DEPTH: 11,
+ REQ_NEWS_BULLETINS: 12,
+ CANCEL_NEWS_BULLETINS: 13,
+ SET_SERVER_LOGLEVEL: 14,
+ REQ_AUTO_OPEN_ORDERS: 15,
+ REQ_ALL_OPEN_ORDERS: 16,
+ REQ_MANAGED_ACCTS: 17,
+ REQ_FA: 18,
+ REPLACE_FA: 19,
+ REQ_HISTORICAL_DATA: 20,
+ EXERCISE_OPTIONS: 21,
+ REQ_SCANNER_SUBSCRIPTION: 22,
+ CANCEL_SCANNER_SUBSCRIPTION: 23,
+ REQ_SCANNER_PARAMETERS: 24,
+ CANCEL_HISTORICAL_DATA: 25,
+ REQ_CURRENT_TIME: 49,
+ REQ_REAL_TIME_BARS: 50,
+ CANCEL_REAL_TIME_BARS: 51,
+ REQ_FUNDAMENTAL_DATA: 52,
+ CANCEL_FUNDAMENTAL_DATA: 53,
+ REQ_CALC_IMPLIED_VOLAT: 54,
+ REQ_CALC_OPTION_PRICE: 55,
+ CANCEL_CALC_IMPLIED_VOLAT: 56,
+ CANCEL_CALC_OPTION_PRICE: 57,
+ REQ_GLOBAL_CANCEL: 58,
+ REQ_MARKET_DATA_TYPE: 59,
+ REQ_POSITIONS: 61,
+ REQ_ACCOUNT_SUMMARY: 62,
+ CANCEL_ACCOUNT_SUMMARY: 63,
+ CANCEL_POSITIONS: 64,
+ VERIFY_REQUEST: 65,
+ VERIFY_MESSAGE: 66,
+ QUERY_DISPLAY_GROUPS: 67,
+ SUBSCRIBE_TO_GROUP_EVENTS: 68,
+ UPDATE_DISPLAY_GROUP: 69,
+ UNSUBSCRIBE_FROM_GROUP_EVENTS: 70,
+ START_API: 71,
+ VERIFY_AND_AUTH_REQUEST: 72,
+ VERIFY_AND_AUTH_MESSAGE: 73,
+ REQ_POSITIONS_MULTI: 74,
+ CANCEL_POSITIONS_MULTI: 75,
+ REQ_ACCOUNT_UPDATES_MULTI: 76,
+ CANCEL_ACCOUNT_UPDATES_MULTI: 77,
+ REQ_SEC_DEF_OPT_PARAMS: 78,
+ REQ_SOFT_DOLLAR_TIERS: 79,
+ REQ_FAMILY_CODES: 80,
+ REQ_MATCHING_SYMBOLS: 81,
+ REQ_MKT_DEPTH_EXCHANGES: 82,
+ REQ_SMART_COMPONENTS: 83,
+ REQ_NEWS_ARTICLE: 84,
+ REQ_NEWS_PROVIDERS: 85,
+ REQ_HISTORICAL_NEWS: 86,
+ REQ_HEAD_TIMESTAMP: 87,
+ REQ_HISTOGRAM_DATA: 88,
+ CANCEL_HISTOGRAM_DATA: 89,
+ CANCEL_HEAD_TIMESTAMP: 90,
+ REQ_MARKET_RULE: 91,
+ REQ_PNL: 92,
+ CANCEL_PNL: 93,
+ REQ_PNL_SINGLE: 94,
+ CANCEL_PNL_SINGLE: 95,
+ REQ_HISTORICAL_TICKS: 96,
+ REQ_TICK_BY_TICK_DATA: 97,
+ CANCEL_TICK_BY_TICK_DATA: 98,
+ REQ_COMPLETED_ORDERS: 99,
+ REQ_WSH_META_DATA: 100,
+ CANCEL_WSH_META_DATA: 101,
+ REQ_WSH_EVENT_DATA: 102,
+ CANCEL_WSH_EVENT_DATA: 103,
+ REQ_USER_INFO: 104,
+ REQ_CURRENT_TIME_IN_MILLIS: 105,
+ CANCEL_CONTRACT_DATA: 106,
+ CANCEL_HISTORICAL_TICKS: 107,
+ REQ_CONFIG: 108,
+ UPDATE_CONFIG: 109,
+} as const
diff --git a/packages/ibkr/src/news.ts b/packages/ibkr/src/news.ts
new file mode 100644
index 00000000..8f3dbdb1
--- /dev/null
+++ b/packages/ibkr/src/news.ts
@@ -0,0 +1,11 @@
+/**
+ * TWS news bulletin constants.
+ * Mirrors: ibapi/news.py
+ */
+
+/** Standard IB news bulletin message */
+export const NEWS_MSG = 1
+/** Control message: exchange is available for trading */
+export const EXCHANGE_AVAIL_MSG = 2
+/** Control message: exchange is unavailable for trading */
+export const EXCHANGE_UNAVAIL_MSG = 3
diff --git a/packages/ibkr/src/order-cancel.ts b/packages/ibkr/src/order-cancel.ts
new file mode 100644
index 00000000..a5bd2973
--- /dev/null
+++ b/packages/ibkr/src/order-cancel.ts
@@ -0,0 +1,23 @@
+/**
+ * Mirrors: ibapi/order_cancel.py
+ */
+
+import { UNSET_INTEGER } from './const.js'
+
+function intMaxString(val: number): string {
+ return val === UNSET_INTEGER ? '' : String(val)
+}
+
+export class OrderCancel {
+ manualOrderCancelTime = ''
+ extOperator = ''
+ manualOrderIndicator: number = UNSET_INTEGER
+
+ toString(): string {
+ return (
+ `manualOrderCancelTime: ${this.manualOrderCancelTime}, ` +
+ `extOperator: ${this.extOperator}, ` +
+ `manualOrderIndicator: ${intMaxString(this.manualOrderIndicator)}`
+ )
+ }
+}
diff --git a/packages/ibkr/src/order-condition.ts b/packages/ibkr/src/order-condition.ts
new file mode 100644
index 00000000..5871e401
--- /dev/null
+++ b/packages/ibkr/src/order-condition.ts
@@ -0,0 +1,398 @@
+/**
+ * Mirrors: ibapi/order_condition.py
+ */
+
+import { UNSET_DOUBLE } from './const.js'
+
+// Helper to pull next value from an iterator
+function nextField(fields: Iterator): string {
+ const r = fields.next()
+ if (r.done) throw new Error('unexpected end')
+ return r.value
+}
+
+function decodeBool(fields: Iterator): boolean {
+ return parseInt(nextField(fields), 10) !== 0
+}
+
+function decodeInt(fields: Iterator): number {
+ return parseInt(nextField(fields), 10)
+}
+
+function decodeStr(fields: Iterator): string {
+ return nextField(fields)
+}
+
+function makeField(val: unknown): string {
+ if (typeof val === 'boolean') return val ? '1' : '0'
+ return String(val ?? '')
+}
+
+export class OrderCondition {
+ static readonly Price = 1
+ static readonly Time = 3
+ static readonly Margin = 4
+ static readonly Execution = 5
+ static readonly Volume = 6
+ static readonly PercentChange = 7
+
+ condType: number
+ isConjunctionConnection = true
+
+ constructor(condType: number) {
+ this.condType = condType
+ }
+
+ type(): number {
+ return this.condType
+ }
+
+ And(): this {
+ this.isConjunctionConnection = true
+ return this
+ }
+
+ Or(): this {
+ this.isConjunctionConnection = false
+ return this
+ }
+
+ decode(fields: Iterator): void {
+ const connector = decodeStr(fields)
+ this.isConjunctionConnection = connector === 'a'
+ }
+
+ makeFields(): string[] {
+ return [makeField(this.isConjunctionConnection ? 'a' : 'o')]
+ }
+
+ toString(): string {
+ return this.isConjunctionConnection ? '' : ''
+ }
+}
+
+export class ExecutionCondition extends OrderCondition {
+ secType: string | null
+ exchange: string | null
+ symbol: string | null
+
+ constructor(secType: string | null = null, exch: string | null = null, symbol: string | null = null) {
+ super(OrderCondition.Execution)
+ this.secType = secType
+ this.exchange = exch
+ this.symbol = symbol
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ this.secType = decodeStr(fields)
+ this.exchange = decodeStr(fields)
+ this.symbol = decodeStr(fields)
+ }
+
+ makeFields(): string[] {
+ return [
+ ...super.makeFields(),
+ makeField(this.secType),
+ makeField(this.exchange),
+ makeField(this.symbol),
+ ]
+ }
+
+ toString(): string {
+ return (
+ 'trade occurs for ' +
+ this.symbol +
+ ' symbol on ' +
+ this.exchange +
+ ' exchange for ' +
+ this.secType +
+ ' security type'
+ )
+ }
+}
+
+export abstract class OperatorCondition extends OrderCondition {
+ isMore: boolean | null
+
+ constructor(condType: number | null = null, isMore: boolean | null = null) {
+ super(condType ?? 0)
+ this.isMore = isMore
+ }
+
+ abstract valueToString(): string
+ abstract setValueFromString(text: string): void
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ this.isMore = decodeBool(fields)
+ const text = decodeStr(fields)
+ this.setValueFromString(text)
+ }
+
+ makeFields(): string[] {
+ return [
+ ...super.makeFields(),
+ makeField(this.isMore),
+ makeField(this.valueToString()),
+ ]
+ }
+
+ toString(): string {
+ const sb = this.isMore ? '>= ' : '<= '
+ return ` ${sb} ${this.valueToString()}`
+ }
+}
+
+export class MarginCondition extends OperatorCondition {
+ percent: number | null
+
+ constructor(isMore: boolean | null = null, percent: number | null = null) {
+ super(OrderCondition.Margin, isMore)
+ this.percent = percent
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ }
+
+ makeFields(): string[] {
+ return super.makeFields()
+ }
+
+ valueToString(): string {
+ return String(this.percent)
+ }
+
+ setValueFromString(text: string): void {
+ this.percent = parseFloat(text)
+ }
+
+ toString(): string {
+ return `the margin cushion percent ${OperatorCondition.prototype.toString.call(this)} `
+ }
+}
+
+export class ContractCondition extends OperatorCondition {
+ conId: number | null
+ exchange: string | null
+
+ constructor(
+ condType: number | null = null,
+ conId: number | null = null,
+ exch: string | null = null,
+ isMore: boolean | null = null,
+ ) {
+ super(condType, isMore)
+ this.conId = conId
+ this.exchange = exch
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ this.conId = decodeInt(fields)
+ this.exchange = decodeStr(fields)
+ }
+
+ makeFields(): string[] {
+ return [
+ ...super.makeFields(),
+ makeField(this.conId),
+ makeField(this.exchange),
+ ]
+ }
+
+ valueToString(): string {
+ return ''
+ }
+
+ setValueFromString(_text: string): void {
+ // todo
+ }
+
+ toString(): string {
+ return `${this.conId} on ${this.exchange} is ${OperatorCondition.prototype.toString.call(this)} `
+ }
+}
+
+export class TimeCondition extends OperatorCondition {
+ time: string | null
+
+ constructor(isMore: boolean | null = null, time: string | null = null) {
+ super(OrderCondition.Time, isMore)
+ this.time = time
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ }
+
+ makeFields(): string[] {
+ return super.makeFields()
+ }
+
+ valueToString(): string {
+ return this.time ?? ''
+ }
+
+ setValueFromString(text: string): void {
+ this.time = text
+ }
+
+ toString(): string {
+ return `time is ${OperatorCondition.prototype.toString.call(this)} `
+ }
+}
+
+export const TriggerMethodEnum = {
+ Default: 0,
+ DoubleBidAsk: 1,
+ Last: 2,
+ DoubleLast: 3,
+ BidAsk: 4,
+ 'N/A1': 5,
+ 'N/A2': 6,
+ LastBidAsk: 7,
+ MidPoint: 8,
+} as const
+
+const TriggerMethodNames = [
+ 'Default',
+ 'DoubleBidAsk',
+ 'Last',
+ 'DoubleLast',
+ 'BidAsk',
+ 'N/A1',
+ 'N/A2',
+ 'LastBidAsk',
+ 'MidPoint',
+]
+
+export class PriceCondition extends ContractCondition {
+ price: number | null
+ triggerMethod: number | null
+
+ constructor(
+ triggerMethod: number | null = null,
+ conId: number | null = null,
+ exch: string | null = null,
+ isMore: boolean | null = null,
+ price: number | null = null,
+ ) {
+ super(OrderCondition.Price, conId, exch, isMore)
+ this.price = price
+ this.triggerMethod = triggerMethod
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ this.triggerMethod = decodeInt(fields)
+ }
+
+ makeFields(): string[] {
+ return [
+ ...super.makeFields(),
+ makeField(this.triggerMethod),
+ ]
+ }
+
+ valueToString(): string {
+ return String(this.price)
+ }
+
+ setValueFromString(text: string): void {
+ this.price = parseFloat(text)
+ }
+
+ toString(): string {
+ const methodName = TriggerMethodNames[this.triggerMethod ?? 0] ?? String(this.triggerMethod)
+ return `${methodName} price of ${ContractCondition.prototype.toString.call(this)} `
+ }
+}
+
+export class PercentChangeCondition extends ContractCondition {
+ changePercent: number
+
+ constructor(
+ conId: number | null = null,
+ exch: string | null = null,
+ isMore: boolean | null = null,
+ changePercent: number = UNSET_DOUBLE,
+ ) {
+ super(OrderCondition.PercentChange, conId, exch, isMore)
+ this.changePercent = changePercent
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ }
+
+ makeFields(): string[] {
+ return super.makeFields()
+ }
+
+ valueToString(): string {
+ return String(this.changePercent)
+ }
+
+ setValueFromString(text: string): void {
+ this.changePercent = parseFloat(text)
+ }
+
+ toString(): string {
+ return `percent change of ${ContractCondition.prototype.toString.call(this)} `
+ }
+}
+
+export class VolumeCondition extends ContractCondition {
+ volume: number | null
+
+ constructor(
+ conId: number | null = null,
+ exch: string | null = null,
+ isMore: boolean | null = null,
+ volume: number | null = null,
+ ) {
+ super(OrderCondition.Volume, conId, exch, isMore)
+ this.volume = volume
+ }
+
+ decode(fields: Iterator): void {
+ super.decode(fields)
+ }
+
+ makeFields(): string[] {
+ return super.makeFields()
+ }
+
+ valueToString(): string {
+ return String(this.volume)
+ }
+
+ setValueFromString(text: string): void {
+ this.volume = parseInt(text, 10)
+ }
+
+ toString(): string {
+ return `volume of ${ContractCondition.prototype.toString.call(this)} `
+ }
+}
+
+export function Create(condType: number): OrderCondition | null {
+ switch (condType) {
+ case OrderCondition.Execution:
+ return new ExecutionCondition()
+ case OrderCondition.Margin:
+ return new MarginCondition()
+ case OrderCondition.PercentChange:
+ return new PercentChangeCondition()
+ case OrderCondition.Price:
+ return new PriceCondition()
+ case OrderCondition.Time:
+ return new TimeCondition()
+ case OrderCondition.Volume:
+ return new VolumeCondition()
+ default:
+ return null
+ }
+}
diff --git a/packages/ibkr/src/order-decoder.ts b/packages/ibkr/src/order-decoder.ts
new file mode 100644
index 00000000..19baf6e2
--- /dev/null
+++ b/packages/ibkr/src/order-decoder.ts
@@ -0,0 +1,703 @@
+/**
+ * Mirrors: ibapi/orderdecoder.py
+ */
+
+import Decimal from 'decimal.js'
+import { UNSET_DOUBLE, UNSET_INTEGER, UNSET_DECIMAL } from './const.js'
+import { Contract, ComboLeg, DeltaNeutralContract } from './contract.js'
+import { Order, OrderComboLeg } from './order.js'
+import { OrderState, OrderAllocation } from './order-state.js'
+import { OrderCondition, Create as createOrderCondition } from './order-condition.js'
+import { SoftDollarTier } from './softdollartier.js'
+import { TagValue } from './tag-value.js'
+import { IneligibilityReason } from './ineligibility-reason.js'
+import {
+ decodeStr,
+ decodeInt,
+ decodeFloat,
+ decodeBool,
+ decodeDecimal,
+ SHOW_UNSET,
+ isPegBenchOrder,
+} from './utils.js'
+import {
+ MIN_SERVER_VER_FA_PROFILE_DESUPPORT,
+ MIN_SERVER_VER_MODELS_SUPPORT,
+ MIN_SERVER_VER_SSHORTX_OLD,
+ MIN_SERVER_VER_WHAT_IF_EXT_FIELDS,
+ MIN_SERVER_VER_PEGGED_TO_BENCHMARK,
+ MIN_SERVER_VER_SOFT_DOLLAR_TIER,
+ MIN_SERVER_VER_CASH_QTY,
+ MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE,
+ MIN_SERVER_VER_ORDER_CONTAINER,
+ MIN_SERVER_VER_D_PEG_ORDERS,
+ MIN_CLIENT_VER,
+ MIN_SERVER_VER_PRICE_MGMT_ALGO,
+ MIN_SERVER_VER_DURATION,
+ MIN_SERVER_VER_POST_TO_ATS,
+ MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS,
+ MIN_SERVER_VER_CUSTOMER_ACCOUNT,
+ MIN_SERVER_VER_PROFESSIONAL_CUSTOMER,
+ MIN_SERVER_VER_BOND_ACCRUED_INTEREST,
+ MIN_SERVER_VER_INCLUDE_OVERNIGHT,
+ MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER,
+ MIN_SERVER_VER_FULL_ORDER_PREVIEW_FIELDS,
+ MIN_SERVER_VER_SUBMITTER,
+} from './server-versions.js'
+
+export class OrderDecoder {
+ contract: Contract
+ order: Order
+ orderState: OrderState
+ version: number
+ serverVersion: number
+
+ constructor(
+ contract: Contract,
+ order: Order,
+ orderState: OrderState,
+ version: number,
+ serverVersion: number,
+ ) {
+ this.contract = contract
+ this.order = order
+ this.orderState = orderState
+ this.version = version
+ this.serverVersion = serverVersion
+ }
+
+ decodeOrderId(fields: Iterator): void {
+ this.order.orderId = decodeInt(fields)
+ }
+
+ decodeContractFields(fields: Iterator): void {
+ this.contract.conId = decodeInt(fields)
+ this.contract.symbol = decodeStr(fields)
+ this.contract.secType = decodeStr(fields)
+ this.contract.lastTradeDateOrContractMonth = decodeStr(fields)
+ this.contract.strike = decodeFloat(fields)
+ this.contract.right = decodeStr(fields)
+ if (this.version >= 32) {
+ this.contract.multiplier = decodeStr(fields)
+ }
+ this.contract.exchange = decodeStr(fields)
+ this.contract.currency = decodeStr(fields)
+ this.contract.localSymbol = decodeStr(fields)
+ if (this.version >= 32) {
+ this.contract.tradingClass = decodeStr(fields)
+ }
+ }
+
+ decodeAction(fields: Iterator): void {
+ this.order.action = decodeStr(fields)
+ }
+
+ decodeTotalQuantity(fields: Iterator): void {
+ this.order.totalQuantity = decodeDecimal(fields)
+ }
+
+ decodeOrderType(fields: Iterator): void {
+ this.order.orderType = decodeStr(fields)
+ }
+
+ decodeLmtPrice(fields: Iterator): void {
+ if (this.version < 29) {
+ this.order.lmtPrice = decodeFloat(fields)
+ } else {
+ this.order.lmtPrice = decodeFloat(fields, SHOW_UNSET)
+ }
+ }
+
+ decodeAuxPrice(fields: Iterator): void {
+ if (this.version < 30) {
+ this.order.auxPrice = decodeFloat(fields)
+ } else {
+ this.order.auxPrice = decodeFloat(fields, SHOW_UNSET)
+ }
+ }
+
+ decodeTIF(fields: Iterator): void {
+ this.order.tif = decodeStr(fields)
+ }
+
+ decodeOcaGroup(fields: Iterator): void {
+ this.order.ocaGroup = decodeStr(fields)
+ }
+
+ decodeAccount(fields: Iterator): void {
+ this.order.account = decodeStr(fields)
+ }
+
+ decodeOpenClose(fields: Iterator): void {
+ this.order.openClose = decodeStr(fields)
+ }
+
+ decodeOrigin(fields: Iterator): void {
+ this.order.origin = decodeInt(fields)
+ }
+
+ decodeOrderRef(fields: Iterator): void {
+ this.order.orderRef = decodeStr(fields)
+ }
+
+ decodeClientId(fields: Iterator): void {
+ this.order.clientId = decodeInt(fields)
+ }
+
+ decodePermId(fields: Iterator): void {
+ this.order.permId = decodeInt(fields)
+ }
+
+ decodeOutsideRth(fields: Iterator): void {
+ this.order.outsideRth = decodeBool(fields)
+ }
+
+ decodeHidden(fields: Iterator): void {
+ this.order.hidden = decodeBool(fields)
+ }
+
+ decodeDiscretionaryAmt(fields: Iterator): void {
+ this.order.discretionaryAmt = decodeFloat(fields)
+ }
+
+ decodeGoodAfterTime(fields: Iterator): void {
+ this.order.goodAfterTime = decodeStr(fields)
+ }
+
+ skipSharesAllocation(fields: Iterator): void {
+ decodeStr(fields) // deprecated
+ }
+
+ decodeFAParams(fields: Iterator): void {
+ this.order.faGroup = decodeStr(fields)
+ this.order.faMethod = decodeStr(fields)
+ this.order.faPercentage = decodeStr(fields)
+ if (this.serverVersion < MIN_SERVER_VER_FA_PROFILE_DESUPPORT) {
+ decodeStr(fields) // skip deprecated faProfile field
+ }
+ }
+
+ decodeModelCode(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_MODELS_SUPPORT) {
+ this.order.modelCode = decodeStr(fields)
+ }
+ }
+
+ decodeGoodTillDate(fields: Iterator): void {
+ this.order.goodTillDate = decodeStr(fields)
+ }
+
+ decodeRule80A(fields: Iterator): void {
+ this.order.rule80A = decodeStr(fields)
+ }
+
+ decodePercentOffset(fields: Iterator): void {
+ this.order.percentOffset = decodeFloat(fields, SHOW_UNSET)
+ }
+
+ decodeSettlingFirm(fields: Iterator): void {
+ this.order.settlingFirm = decodeStr(fields)
+ }
+
+ decodeShortSaleParams(fields: Iterator): void {
+ this.order.shortSaleSlot = decodeInt(fields)
+ this.order.designatedLocation = decodeStr(fields)
+ if (this.serverVersion === MIN_SERVER_VER_SSHORTX_OLD) {
+ decodeInt(fields)
+ } else if (this.version >= 23) {
+ this.order.exemptCode = decodeInt(fields)
+ }
+ }
+
+ decodeAuctionStrategy(fields: Iterator): void {
+ this.order.auctionStrategy = decodeInt(fields)
+ }
+
+ decodeBoxOrderParams(fields: Iterator): void {
+ this.order.startingPrice = decodeFloat(fields, SHOW_UNSET)
+ this.order.stockRefPrice = decodeFloat(fields, SHOW_UNSET)
+ this.order.delta = decodeFloat(fields, SHOW_UNSET)
+ }
+
+ decodePegToStkOrVolOrderParams(fields: Iterator): void {
+ this.order.stockRangeLower = decodeFloat(fields, SHOW_UNSET)
+ this.order.stockRangeUpper = decodeFloat(fields, SHOW_UNSET)
+ }
+
+ decodeDisplaySize(fields: Iterator): void {
+ this.order.displaySize = decodeInt(fields, SHOW_UNSET)
+ }
+
+ decodeBlockOrder(fields: Iterator): void {
+ this.order.blockOrder = decodeBool(fields)
+ }
+
+ decodeSweepToFill(fields: Iterator): void {
+ this.order.sweepToFill = decodeBool(fields)
+ }
+
+ decodeAllOrNone(fields: Iterator): void {
+ this.order.allOrNone = decodeBool(fields)
+ }
+
+ decodeMinQty(fields: Iterator): void {
+ this.order.minQty = decodeInt(fields, SHOW_UNSET)
+ }
+
+ decodeOcaType(fields: Iterator): void {
+ this.order.ocaType = decodeInt(fields)
+ }
+
+ skipETradeOnly(fields: Iterator): void {
+ decodeBool(fields) // deprecated
+ }
+
+ skipFirmQuoteOnly(fields: Iterator): void {
+ decodeBool(fields) // deprecated
+ }
+
+ skipNbboPriceCap(fields: Iterator): void {
+ decodeFloat(fields, SHOW_UNSET) // deprecated
+ }
+
+ decodeParentId(fields: Iterator): void {
+ this.order.parentId = decodeInt(fields)
+ }
+
+ decodeTriggerMethod(fields: Iterator): void {
+ this.order.triggerMethod = decodeInt(fields)
+ }
+
+ decodeVolOrderParams(fields: Iterator, readOpenOrderAttribs: boolean): void {
+ this.order.volatility = decodeFloat(fields, SHOW_UNSET)
+ this.order.volatilityType = decodeInt(fields)
+ this.order.deltaNeutralOrderType = decodeStr(fields)
+ this.order.deltaNeutralAuxPrice = decodeFloat(fields, SHOW_UNSET)
+
+ if (this.version >= 27 && this.order.deltaNeutralOrderType) {
+ this.order.deltaNeutralConId = decodeInt(fields)
+ if (readOpenOrderAttribs) {
+ this.order.deltaNeutralSettlingFirm = decodeStr(fields)
+ this.order.deltaNeutralClearingAccount = decodeStr(fields)
+ this.order.deltaNeutralClearingIntent = decodeStr(fields)
+ }
+ }
+
+ if (this.version >= 31 && this.order.deltaNeutralOrderType) {
+ if (readOpenOrderAttribs) {
+ this.order.deltaNeutralOpenClose = decodeStr(fields)
+ }
+ this.order.deltaNeutralShortSale = decodeBool(fields)
+ this.order.deltaNeutralShortSaleSlot = decodeInt(fields)
+ this.order.deltaNeutralDesignatedLocation = decodeStr(fields)
+ }
+
+ this.order.continuousUpdate = decodeBool(fields)
+ this.order.referencePriceType = decodeInt(fields)
+ }
+
+ decodeTrailParams(fields: Iterator): void {
+ this.order.trailStopPrice = decodeFloat(fields, SHOW_UNSET)
+ if (this.version >= 30) {
+ this.order.trailingPercent = decodeFloat(fields, SHOW_UNSET)
+ }
+ }
+
+ decodeBasisPoints(fields: Iterator): void {
+ this.order.basisPoints = decodeFloat(fields, SHOW_UNSET)
+ this.order.basisPointsType = decodeInt(fields, SHOW_UNSET)
+ }
+
+ decodeComboLegs(fields: Iterator): void {
+ this.contract.comboLegsDescrip = decodeStr(fields)
+
+ if (this.version >= 29) {
+ const comboLegsCount = decodeInt(fields)
+
+ if (comboLegsCount > 0) {
+ this.contract.comboLegs = []
+ for (let i = 0; i < comboLegsCount; i++) {
+ const comboLeg = new ComboLeg()
+ comboLeg.conId = decodeInt(fields)
+ comboLeg.ratio = decodeInt(fields)
+ comboLeg.action = decodeStr(fields)
+ comboLeg.exchange = decodeStr(fields)
+ comboLeg.openClose = decodeInt(fields)
+ comboLeg.shortSaleSlot = decodeInt(fields)
+ comboLeg.designatedLocation = decodeStr(fields)
+ comboLeg.exemptCode = decodeInt(fields)
+ this.contract.comboLegs.push(comboLeg)
+ }
+ }
+
+ const orderComboLegsCount = decodeInt(fields)
+ if (orderComboLegsCount > 0) {
+ this.order.orderComboLegs = []
+ for (let i = 0; i < orderComboLegsCount; i++) {
+ const orderComboLeg = new OrderComboLeg()
+ orderComboLeg.price = decodeFloat(fields, SHOW_UNSET)
+ this.order.orderComboLegs.push(orderComboLeg)
+ }
+ }
+ }
+ }
+
+ decodeSmartComboRoutingParams(fields: Iterator): void {
+ if (this.version >= 26) {
+ const smartComboRoutingParamsCount = decodeInt(fields)
+ if (smartComboRoutingParamsCount > 0) {
+ this.order.smartComboRoutingParams = []
+ for (let i = 0; i < smartComboRoutingParamsCount; i++) {
+ const tagValue = new TagValue()
+ tagValue.tag = decodeStr(fields)
+ tagValue.value = decodeStr(fields)
+ this.order.smartComboRoutingParams.push(tagValue)
+ }
+ }
+ }
+ }
+
+ decodeScaleOrderParams(fields: Iterator): void {
+ if (this.version >= 20) {
+ this.order.scaleInitLevelSize = decodeInt(fields, SHOW_UNSET)
+ this.order.scaleSubsLevelSize = decodeInt(fields, SHOW_UNSET)
+ } else {
+ decodeInt(fields, SHOW_UNSET) // notSuppScaleNumComponents (deprecated)
+ this.order.scaleInitLevelSize = decodeInt(fields, SHOW_UNSET)
+ }
+
+ this.order.scalePriceIncrement = decodeFloat(fields, SHOW_UNSET)
+
+ if (
+ this.version >= 28 &&
+ this.order.scalePriceIncrement !== UNSET_DOUBLE &&
+ this.order.scalePriceIncrement > 0.0
+ ) {
+ this.order.scalePriceAdjustValue = decodeFloat(fields, SHOW_UNSET)
+ this.order.scalePriceAdjustInterval = decodeInt(fields, SHOW_UNSET)
+ this.order.scaleProfitOffset = decodeFloat(fields, SHOW_UNSET)
+ this.order.scaleAutoReset = decodeBool(fields)
+ this.order.scaleInitPosition = decodeInt(fields, SHOW_UNSET)
+ this.order.scaleInitFillQty = decodeInt(fields, SHOW_UNSET)
+ this.order.scaleRandomPercent = decodeBool(fields)
+ }
+ }
+
+ decodeHedgeParams(fields: Iterator): void {
+ if (this.version >= 24) {
+ this.order.hedgeType = decodeStr(fields)
+ if (this.order.hedgeType) {
+ this.order.hedgeParam = decodeStr(fields)
+ }
+ }
+ }
+
+ decodeOptOutSmartRouting(fields: Iterator): void {
+ if (this.version >= 25) {
+ this.order.optOutSmartRouting = decodeBool(fields)
+ }
+ }
+
+ decodeClearingParams(fields: Iterator): void {
+ this.order.clearingAccount = decodeStr(fields)
+ this.order.clearingIntent = decodeStr(fields)
+ }
+
+ decodeNotHeld(fields: Iterator): void {
+ if (this.version >= 22) {
+ this.order.notHeld = decodeBool(fields)
+ }
+ }
+
+ decodeDeltaNeutral(fields: Iterator): void {
+ if (this.version >= 20) {
+ const deltaNeutralContractPresent = decodeBool(fields)
+ if (deltaNeutralContractPresent) {
+ this.contract.deltaNeutralContract = new DeltaNeutralContract()
+ this.contract.deltaNeutralContract.conId = decodeInt(fields)
+ this.contract.deltaNeutralContract.delta = decodeFloat(fields)
+ this.contract.deltaNeutralContract.price = decodeFloat(fields)
+ }
+ }
+ }
+
+ decodeAlgoParams(fields: Iterator): void {
+ if (this.version >= 21) {
+ this.order.algoStrategy = decodeStr(fields)
+ if (this.order.algoStrategy) {
+ const algoParamsCount = decodeInt(fields)
+ if (algoParamsCount > 0) {
+ this.order.algoParams = []
+ for (let i = 0; i < algoParamsCount; i++) {
+ const tagValue = new TagValue()
+ tagValue.tag = decodeStr(fields)
+ tagValue.value = decodeStr(fields)
+ this.order.algoParams.push(tagValue)
+ }
+ }
+ }
+ }
+ }
+
+ decodeSolicited(fields: Iterator): void {
+ if (this.version >= 33) {
+ this.order.solicited = decodeBool(fields)
+ }
+ }
+
+ decodeOrderStatus(fields: Iterator): void {
+ this.orderState.status = decodeStr(fields)
+ }
+
+ decodeWhatIfInfoAndCommissionAndFees(fields: Iterator): void {
+ this.order.whatIf = decodeBool(fields)
+ this.decodeOrderStatus(fields)
+ if (this.serverVersion >= MIN_SERVER_VER_WHAT_IF_EXT_FIELDS) {
+ this.orderState.initMarginBefore = decodeStr(fields)
+ this.orderState.maintMarginBefore = decodeStr(fields)
+ this.orderState.equityWithLoanBefore = decodeStr(fields)
+ this.orderState.initMarginChange = decodeStr(fields)
+ this.orderState.maintMarginChange = decodeStr(fields)
+ this.orderState.equityWithLoanChange = decodeStr(fields)
+ }
+
+ this.orderState.initMarginAfter = decodeStr(fields)
+ this.orderState.maintMarginAfter = decodeStr(fields)
+ this.orderState.equityWithLoanAfter = decodeStr(fields)
+
+ this.orderState.commissionAndFees = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.minCommissionAndFees = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.maxCommissionAndFees = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.commissionAndFeesCurrency = decodeStr(fields)
+
+ if (this.serverVersion >= MIN_SERVER_VER_FULL_ORDER_PREVIEW_FIELDS) {
+ this.orderState.marginCurrency = decodeStr(fields)
+ this.orderState.initMarginBeforeOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.maintMarginBeforeOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.equityWithLoanBeforeOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.initMarginChangeOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.maintMarginChangeOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.equityWithLoanChangeOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.initMarginAfterOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.maintMarginAfterOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.equityWithLoanAfterOutsideRTH = decodeFloat(fields, SHOW_UNSET)
+ this.orderState.suggestedSize = decodeDecimal(fields)
+ this.orderState.rejectReason = decodeStr(fields)
+
+ const accountsCount = decodeInt(fields)
+ if (accountsCount > 0) {
+ this.orderState.orderAllocations = []
+ for (let i = 0; i < accountsCount; i++) {
+ const orderAllocation = new OrderAllocation()
+ orderAllocation.account = decodeStr(fields)
+ orderAllocation.position = decodeDecimal(fields)
+ orderAllocation.positionDesired = decodeDecimal(fields)
+ orderAllocation.positionAfter = decodeDecimal(fields)
+ orderAllocation.desiredAllocQty = decodeDecimal(fields)
+ orderAllocation.allowedAllocQty = decodeDecimal(fields)
+ orderAllocation.isMonetary = decodeBool(fields)
+ this.orderState.orderAllocations.push(orderAllocation)
+ }
+ }
+ }
+ this.orderState.warningText = decodeStr(fields)
+ }
+
+ decodeVolRandomizeFlags(fields: Iterator): void {
+ if (this.version >= 34) {
+ this.order.randomizeSize = decodeBool(fields)
+ this.order.randomizePrice = decodeBool(fields)
+ }
+ }
+
+ decodePegToBenchParams(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK) {
+ if (isPegBenchOrder(this.order.orderType)) {
+ this.order.referenceContractId = decodeInt(fields)
+ this.order.isPeggedChangeAmountDecrease = decodeBool(fields)
+ this.order.peggedChangeAmount = decodeFloat(fields)
+ this.order.referenceChangeAmount = decodeFloat(fields)
+ this.order.referenceExchangeId = decodeStr(fields)
+ }
+ }
+ }
+
+ decodeConditions(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK) {
+ const conditionsSize = decodeInt(fields)
+ if (conditionsSize > 0) {
+ this.order.conditions = []
+ for (let i = 0; i < conditionsSize; i++) {
+ const conditionType = decodeInt(fields)
+ const condition = createOrderCondition(conditionType)
+ if (condition) {
+ condition.decode(fields)
+ this.order.conditions.push(condition)
+ }
+ }
+
+ this.order.conditionsIgnoreRth = decodeBool(fields)
+ this.order.conditionsCancelOrder = decodeBool(fields)
+ }
+ }
+ }
+
+ decodeAdjustedOrderParams(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_PEGGED_TO_BENCHMARK) {
+ this.order.adjustedOrderType = decodeStr(fields)
+ this.order.triggerPrice = decodeFloat(fields)
+ this.decodeStopPriceAndLmtPriceOffset(fields)
+ this.order.adjustedStopPrice = decodeFloat(fields)
+ this.order.adjustedStopLimitPrice = decodeFloat(fields)
+ this.order.adjustedTrailingAmount = decodeFloat(fields)
+ this.order.adjustableTrailingUnit = decodeInt(fields)
+ }
+ }
+
+ decodeStopPriceAndLmtPriceOffset(fields: Iterator): void {
+ this.order.trailStopPrice = decodeFloat(fields)
+ this.order.lmtPriceOffset = decodeFloat(fields)
+ }
+
+ decodeSoftDollarTier(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_SOFT_DOLLAR_TIER) {
+ const name = decodeStr(fields)
+ const value = decodeStr(fields)
+ const displayName = decodeStr(fields)
+ this.order.softDollarTier = new SoftDollarTier(name, value, displayName)
+ }
+ }
+
+ decodeCashQty(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_CASH_QTY) {
+ this.order.cashQty = decodeFloat(fields)
+ }
+ }
+
+ decodeDontUseAutoPriceForHedge(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE) {
+ this.order.dontUseAutoPriceForHedge = decodeBool(fields)
+ }
+ }
+
+ decodeIsOmsContainers(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_ORDER_CONTAINER) {
+ this.order.isOmsContainer = decodeBool(fields)
+ }
+ }
+
+ decodeDiscretionaryUpToLimitPrice(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_D_PEG_ORDERS) {
+ this.order.discretionaryUpToLimitPrice = decodeBool(fields)
+ }
+ }
+
+ decodeAutoCancelDate(fields: Iterator): void {
+ this.order.autoCancelDate = decodeStr(fields)
+ }
+
+ decodeFilledQuantity(fields: Iterator): void {
+ this.order.filledQuantity = decodeDecimal(fields)
+ }
+
+ decodeRefFuturesConId(fields: Iterator): void {
+ this.order.refFuturesConId = decodeInt(fields)
+ }
+
+ decodeAutoCancelParent(fields: Iterator, minVersionAutoCancelParent: number = MIN_CLIENT_VER): void {
+ if (this.serverVersion >= minVersionAutoCancelParent) {
+ this.order.autoCancelParent = decodeBool(fields)
+ }
+ }
+
+ decodeShareholder(fields: Iterator): void {
+ this.order.shareholder = decodeStr(fields)
+ }
+
+ decodeImbalanceOnly(fields: Iterator, minVersionImbalanceOnly: number = MIN_CLIENT_VER): void {
+ if (this.serverVersion >= minVersionImbalanceOnly) {
+ this.order.imbalanceOnly = decodeBool(fields)
+ }
+ }
+
+ decodeRouteMarketableToBbo(fields: Iterator): void {
+ this.order.routeMarketableToBbo = decodeBool(fields)
+ }
+
+ decodeParentPermId(fields: Iterator): void {
+ this.order.parentPermId = decodeInt(fields)
+ }
+
+ decodeCompletedTime(fields: Iterator): void {
+ this.orderState.completedTime = decodeStr(fields)
+ }
+
+ decodeCompletedStatus(fields: Iterator): void {
+ this.orderState.completedStatus = decodeStr(fields)
+ }
+
+ decodeUsePriceMgmtAlgo(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_PRICE_MGMT_ALGO) {
+ this.order.usePriceMgmtAlgo = decodeBool(fields)
+ }
+ }
+
+ decodeDuration(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_DURATION) {
+ this.order.duration = decodeInt(fields, SHOW_UNSET)
+ }
+ }
+
+ decodePostToAts(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_POST_TO_ATS) {
+ this.order.postToAts = decodeInt(fields, SHOW_UNSET)
+ }
+ }
+
+ decodePegBestPegMidOrderAttributes(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS) {
+ this.order.minTradeQty = decodeInt(fields, SHOW_UNSET)
+ this.order.minCompeteSize = decodeInt(fields, SHOW_UNSET)
+ this.order.competeAgainstBestOffset = decodeFloat(fields, SHOW_UNSET)
+ this.order.midOffsetAtWhole = decodeFloat(fields, SHOW_UNSET)
+ this.order.midOffsetAtHalf = decodeFloat(fields, SHOW_UNSET)
+ }
+ }
+
+ decodeCustomerAccount(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_CUSTOMER_ACCOUNT) {
+ this.order.customerAccount = decodeStr(fields)
+ }
+ }
+
+ decodeProfessionalCustomer(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_PROFESSIONAL_CUSTOMER) {
+ this.order.professionalCustomer = decodeBool(fields)
+ }
+ }
+
+ decodeBondAccruedInterest(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_BOND_ACCRUED_INTEREST) {
+ this.order.bondAccruedInterest = decodeStr(fields)
+ }
+ }
+
+ decodeIncludeOvernight(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_INCLUDE_OVERNIGHT) {
+ this.order.includeOvernight = decodeBool(fields)
+ }
+ }
+
+ decodeCMETaggingFields(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER) {
+ this.order.extOperator = decodeStr(fields)
+ this.order.manualOrderIndicator = decodeInt(fields, SHOW_UNSET)
+ }
+ }
+
+ decodeSubmitter(fields: Iterator): void {
+ if (this.serverVersion >= MIN_SERVER_VER_SUBMITTER) {
+ this.order.submitter = decodeStr(fields)
+ }
+ }
+}
diff --git a/packages/ibkr/src/order-state.ts b/packages/ibkr/src/order-state.ts
new file mode 100644
index 00000000..b52b5fab
--- /dev/null
+++ b/packages/ibkr/src/order-state.ts
@@ -0,0 +1,113 @@
+/**
+ * Mirrors: ibapi/order_state.py
+ */
+
+import Decimal from 'decimal.js'
+import { UNSET_DOUBLE, UNSET_DECIMAL } from './const.js'
+
+function floatMaxString(val: number): string {
+ return val === UNSET_DOUBLE ? '' : String(val)
+}
+
+function decimalMaxString(val: Decimal): string {
+ return val.eq(UNSET_DECIMAL) ? '' : val.toString()
+}
+
+export class OrderAllocation {
+ account = ''
+ position: Decimal = UNSET_DECIMAL
+ positionDesired: Decimal = UNSET_DECIMAL
+ positionAfter: Decimal = UNSET_DECIMAL
+ desiredAllocQty: Decimal = UNSET_DECIMAL
+ allowedAllocQty: Decimal = UNSET_DECIMAL
+ isMonetary = false
+
+ toString(): string {
+ return (
+ `Account: ${this.account}, Position: ${decimalMaxString(this.position)}, ` +
+ `PositionDesired: ${decimalMaxString(this.positionDesired)}, ` +
+ `PositionAfter: ${decimalMaxString(this.positionAfter)}, ` +
+ `DesiredAllocQty: ${decimalMaxString(this.desiredAllocQty)}, ` +
+ `AllowedAllocQty: ${decimalMaxString(this.allowedAllocQty)}, ` +
+ `IsMonetary: ${this.isMonetary}`
+ )
+ }
+}
+
+export class OrderState {
+ status = ''
+
+ initMarginBefore = ''
+ maintMarginBefore = ''
+ equityWithLoanBefore = ''
+ initMarginChange = ''
+ maintMarginChange = ''
+ equityWithLoanChange = ''
+ initMarginAfter = ''
+ maintMarginAfter = ''
+ equityWithLoanAfter = ''
+
+ commissionAndFees: number = UNSET_DOUBLE
+ minCommissionAndFees: number = UNSET_DOUBLE
+ maxCommissionAndFees: number = UNSET_DOUBLE
+ commissionAndFeesCurrency = ''
+ marginCurrency = ''
+ initMarginBeforeOutsideRTH: number = UNSET_DOUBLE
+ maintMarginBeforeOutsideRTH: number = UNSET_DOUBLE
+ equityWithLoanBeforeOutsideRTH: number = UNSET_DOUBLE
+ initMarginChangeOutsideRTH: number = UNSET_DOUBLE
+ maintMarginChangeOutsideRTH: number = UNSET_DOUBLE
+ equityWithLoanChangeOutsideRTH: number = UNSET_DOUBLE
+ initMarginAfterOutsideRTH: number = UNSET_DOUBLE
+ maintMarginAfterOutsideRTH: number = UNSET_DOUBLE
+ equityWithLoanAfterOutsideRTH: number = UNSET_DOUBLE
+ suggestedSize: Decimal = UNSET_DECIMAL
+ rejectReason = ''
+ orderAllocations: OrderAllocation[] | null = null
+ warningText = ''
+ completedTime = ''
+ completedStatus = ''
+
+ toString(): string {
+ let s =
+ `Status: ${this.status}, ` +
+ `InitMarginBefore: ${this.initMarginBefore}, ` +
+ `MaintMarginBefore: ${this.maintMarginBefore}, ` +
+ `EquityWithLoanBefore: ${this.equityWithLoanBefore}, ` +
+ `InitMarginChange: ${this.initMarginChange}, ` +
+ `MaintMarginChange: ${this.maintMarginChange}, ` +
+ `EquityWithLoanChange: ${this.equityWithLoanChange}, ` +
+ `InitMarginAfter: ${this.initMarginAfter}, ` +
+ `MaintMarginAfter: ${this.maintMarginAfter}, ` +
+ `EquityWithLoanAfter: ${this.equityWithLoanAfter}, ` +
+ `CommissionAndFees: ${floatMaxString(this.commissionAndFees)}, ` +
+ `MinCommissionAndFees: ${floatMaxString(this.minCommissionAndFees)}, ` +
+ `MaxCommissionAndFees: ${floatMaxString(this.maxCommissionAndFees)}, ` +
+ `CommissionAndFeesCurrency: ${this.commissionAndFeesCurrency}, ` +
+ `MarginCurrency: ${this.marginCurrency}, ` +
+ `InitMarginBeforeOutsideRTH: ${floatMaxString(this.initMarginBeforeOutsideRTH)}, ` +
+ `MaintMarginBeforeOutsideRTH: ${floatMaxString(this.maintMarginBeforeOutsideRTH)}, ` +
+ `EquityWithLoanBeforeOutsideRTH: ${floatMaxString(this.equityWithLoanBeforeOutsideRTH)}, ` +
+ `InitMarginChangeOutsideRTH: ${floatMaxString(this.initMarginChangeOutsideRTH)}, ` +
+ `MaintMarginChangeOutsideRTH: ${floatMaxString(this.maintMarginChangeOutsideRTH)}, ` +
+ `equityWithLoanChangeOutsideRTH: ${floatMaxString(this.equityWithLoanChangeOutsideRTH)}, ` +
+ `InitMarginAfterOutsideRTH: ${floatMaxString(this.initMarginAfterOutsideRTH)}, ` +
+ `MaintMarginAfterOutsideRTH: ${floatMaxString(this.maintMarginAfterOutsideRTH)}, ` +
+ `equityWithLoanAfterOutsideRTH: ${floatMaxString(this.equityWithLoanAfterOutsideRTH)}, ` +
+ `SuggestedSize: ${decimalMaxString(this.suggestedSize)}, ` +
+ `RejectReason: ${this.rejectReason}, ` +
+ `WarningText: ${this.warningText}, ` +
+ `CompletedTime: ${this.completedTime}, ` +
+ `CompletedStatus: ${this.completedStatus}`
+
+ if (this.orderAllocations) {
+ s += ' OrderAllocations('
+ for (const orderAllocation of this.orderAllocations) {
+ s += orderAllocation.toString() + '; '
+ }
+ s += ')'
+ }
+
+ return s
+ }
+}
diff --git a/packages/ibkr/src/order.ts b/packages/ibkr/src/order.ts
new file mode 100644
index 00000000..b9be55c8
--- /dev/null
+++ b/packages/ibkr/src/order.ts
@@ -0,0 +1,271 @@
+/**
+ * Mirrors: ibapi/order.py
+ */
+
+import Decimal from 'decimal.js'
+import { UNSET_DOUBLE, UNSET_INTEGER, UNSET_DECIMAL, DOUBLE_INFINITY } from './const.js'
+import { SoftDollarTier } from './softdollartier.js'
+import type { TagValueList } from './tag-value.js'
+import type { OrderCondition } from './order-condition.js'
+
+// enum Origin
+export const CUSTOMER = 0
+export const FIRM = 1
+export const UNKNOWN = 2
+
+// enum AuctionStrategy
+export const AUCTION_UNSET = 0
+export const AUCTION_MATCH = 1
+export const AUCTION_IMPROVEMENT = 2
+export const AUCTION_TRANSPARENT = 3
+
+export const COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID = DOUBLE_INFINITY
+
+function floatMaxString(val: number): string { return val === UNSET_DOUBLE ? '' : String(val) }
+function intMaxString(val: number): string { return val === UNSET_INTEGER ? '' : String(val) }
+function decimalMaxString(val: Decimal): string { return val.equals(UNSET_DECIMAL) ? '' : val.toString() }
+function longMaxString(val: number): string { return val === UNSET_INTEGER ? '' : String(val) }
+
+export class OrderComboLeg {
+ price: number = UNSET_DOUBLE
+
+ toString(): string {
+ return `${floatMaxString(this.price)}`
+ }
+}
+
+export class Order {
+ softDollarTier: SoftDollarTier = new SoftDollarTier('', '', '')
+
+ // order identifier
+ orderId: number = 0
+ clientId: number = 0
+ permId: number = 0
+
+ // main order fields
+ action: string = ''
+ totalQuantity: Decimal = UNSET_DECIMAL
+ orderType: string = ''
+ lmtPrice: number = UNSET_DOUBLE
+ auxPrice: number = UNSET_DOUBLE
+
+ // extended order fields
+ tif: string = '' // "Time in Force" - DAY, GTC, etc.
+ activeStartTime: string = '' // for GTC orders
+ activeStopTime: string = '' // for GTC orders
+ ocaGroup: string = '' // one cancels all group name
+ ocaType: number = 0 // 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK
+ orderRef: string = ''
+ transmit: boolean = true // if false, order will be created but not transmitted
+ parentId: number = 0 // Parent order id, to associate Auto STP or TRAIL orders with the original order.
+ blockOrder: boolean = false
+ sweepToFill: boolean = false
+ displaySize: number = 0
+ triggerMethod: number = 0 // 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point
+ outsideRth: boolean = false
+ hidden: boolean = false
+ goodAfterTime: string = '' // Format: 20060505 08:00:00 {time zone}
+ goodTillDate: string = '' // Format: 20060505 08:00:00 {time zone}
+ rule80A: string = '' // Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N'
+ allOrNone: boolean = false
+ minQty: number = UNSET_INTEGER
+ percentOffset: number = UNSET_DOUBLE // REL orders only
+ overridePercentageConstraints: boolean = false
+ trailStopPrice: number = UNSET_DOUBLE
+ trailingPercent: number = UNSET_DOUBLE // TRAILLIMIT orders only
+
+ // financial advisors only
+ faGroup: string = ''
+ faMethod: string = ''
+ faPercentage: string = ''
+
+ // institutional (ie non-cleared) only
+ designatedLocation: string = '' // used only when shortSaleSlot=2
+ openClose: string = '' // O=Open, C=Close
+ origin: number = CUSTOMER // 0=Customer, 1=Firm
+ shortSaleSlot: number = 0 // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action=SSHORT
+ exemptCode: number = -1
+
+ // SMART routing only
+ discretionaryAmt: number = 0
+ optOutSmartRouting: boolean = false
+
+ // BOX exchange orders only
+ auctionStrategy: number = AUCTION_UNSET // AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT
+ startingPrice: number = UNSET_DOUBLE
+ stockRefPrice: number = UNSET_DOUBLE
+ delta: number = UNSET_DOUBLE
+
+ // pegged to stock and VOL orders only
+ stockRangeLower: number = UNSET_DOUBLE
+ stockRangeUpper: number = UNSET_DOUBLE
+
+ randomizePrice: boolean = false
+ randomizeSize: boolean = false
+
+ // VOLATILITY ORDERS ONLY
+ volatility: number = UNSET_DOUBLE
+ volatilityType: number = UNSET_INTEGER // 1=daily, 2=annual
+ deltaNeutralOrderType: string = ''
+ deltaNeutralAuxPrice: number = UNSET_DOUBLE
+ deltaNeutralConId: number = 0
+ deltaNeutralSettlingFirm: string = ''
+ deltaNeutralClearingAccount: string = ''
+ deltaNeutralClearingIntent: string = ''
+ deltaNeutralOpenClose: string = ''
+ deltaNeutralShortSale: boolean = false
+ deltaNeutralShortSaleSlot: number = 0
+ deltaNeutralDesignatedLocation: string = ''
+ continuousUpdate: boolean = false
+ referencePriceType: number = UNSET_INTEGER // 1=Average, 2 = BidOrAsk
+
+ // COMBO ORDERS ONLY
+ basisPoints: number = UNSET_DOUBLE // EFP orders only
+ basisPointsType: number = UNSET_INTEGER // EFP orders only
+
+ // SCALE ORDERS ONLY
+ scaleInitLevelSize: number = UNSET_INTEGER
+ scaleSubsLevelSize: number = UNSET_INTEGER
+ scalePriceIncrement: number = UNSET_DOUBLE
+ scalePriceAdjustValue: number = UNSET_DOUBLE
+ scalePriceAdjustInterval: number = UNSET_INTEGER
+ scaleProfitOffset: number = UNSET_DOUBLE
+ scaleAutoReset: boolean = false
+ scaleInitPosition: number = UNSET_INTEGER
+ scaleInitFillQty: number = UNSET_INTEGER
+ scaleRandomPercent: boolean = false
+ scaleTable: string = ''
+
+ // HEDGE ORDERS
+ hedgeType: string = '' // 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair
+ hedgeParam: string = '' // 'beta=X' value for beta hedge, 'ratio=Y' for pair hedge
+
+ // Clearing info
+ account: string = '' // IB account
+ settlingFirm: string = ''
+ clearingAccount: string = '' // True beneficiary of the order
+ clearingIntent: string = '' // "" (Default), "IB", "Away", "PTA" (PostTrade)
+
+ // ALGO ORDERS ONLY
+ algoStrategy: string = ''
+
+ algoParams: TagValueList = null
+ smartComboRoutingParams: TagValueList = null
+
+ algoId: string = ''
+
+ // What-if
+ whatIf: boolean = false
+
+ // Not Held
+ notHeld: boolean = false
+ solicited: boolean = false
+
+ // models
+ modelCode: string = ''
+
+ // order combo legs
+ orderComboLegs: OrderComboLeg[] | null = null
+
+ orderMiscOptions: TagValueList = null
+
+ // VER PEG2BENCH fields:
+ referenceContractId: number = 0
+ peggedChangeAmount: number = 0.0
+ isPeggedChangeAmountDecrease: boolean = false
+ referenceChangeAmount: number = 0.0
+ referenceExchangeId: string = ''
+ adjustedOrderType: string = ''
+
+ triggerPrice: number = UNSET_DOUBLE
+ adjustedStopPrice: number = UNSET_DOUBLE
+ adjustedStopLimitPrice: number = UNSET_DOUBLE
+ adjustedTrailingAmount: number = UNSET_DOUBLE
+ adjustableTrailingUnit: number = 0
+ lmtPriceOffset: number = UNSET_DOUBLE
+
+ conditions: OrderCondition[] = []
+ conditionsCancelOrder: boolean = false
+ conditionsIgnoreRth: boolean = false
+
+ // ext operator
+ extOperator: string = ''
+
+ // native cash quantity
+ cashQty: number = UNSET_DOUBLE
+
+ mifid2DecisionMaker: string = ''
+ mifid2DecisionAlgo: string = ''
+ mifid2ExecutionTrader: string = ''
+ mifid2ExecutionAlgo: string = ''
+
+ dontUseAutoPriceForHedge: boolean = false
+
+ isOmsContainer: boolean = false
+
+ discretionaryUpToLimitPrice: boolean = false
+
+ autoCancelDate: string = ''
+ filledQuantity: Decimal = UNSET_DECIMAL
+ refFuturesConId: number = 0
+ autoCancelParent: boolean = false
+ shareholder: string = ''
+ imbalanceOnly: boolean = false
+ routeMarketableToBbo: boolean | null = null
+ parentPermId: number = 0
+
+ usePriceMgmtAlgo: boolean | null = null
+ duration: number = UNSET_INTEGER
+ postToAts: number = UNSET_INTEGER
+ advancedErrorOverride: string = ''
+ manualOrderTime: string = ''
+ minTradeQty: number = UNSET_INTEGER
+ minCompeteSize: number = UNSET_INTEGER
+ competeAgainstBestOffset: number = UNSET_DOUBLE
+ midOffsetAtWhole: number = UNSET_DOUBLE
+ midOffsetAtHalf: number = UNSET_DOUBLE
+ customerAccount: string = ''
+ professionalCustomer: boolean = false
+ bondAccruedInterest: string = ''
+ includeOvernight: boolean = false
+ manualOrderIndicator: number = UNSET_INTEGER
+ submitter: string = ''
+ postOnly: boolean = false
+ allowPreOpen: boolean = false
+ ignoreOpenAuction: boolean = false
+ deactivate: boolean = false
+ seekPriceImprovement: boolean | null = null
+ whatIfType: number = UNSET_INTEGER
+
+ // attached orders
+ slOrderId: number = UNSET_INTEGER
+ slOrderType: string = ''
+ ptOrderId: number = UNSET_INTEGER
+ ptOrderType: string = ''
+
+ toString(): string {
+ let s = `${intMaxString(this.orderId)},${intMaxString(this.clientId)},${longMaxString(this.permId)}:`
+
+ s += ` ${this.orderType} ${this.action} ${decimalMaxString(this.totalQuantity)}@${floatMaxString(this.lmtPrice)}`
+
+ s += ` ${this.tif}`
+
+ if (this.orderComboLegs) {
+ s += ' CMB('
+ for (const leg of this.orderComboLegs) {
+ s += leg.toString() + ','
+ }
+ s += ')'
+ }
+
+ if (this.conditions.length > 0) {
+ s += ' COND('
+ for (const cond of this.conditions) {
+ s += String(cond) + ','
+ }
+ s += ')'
+ }
+
+ return s
+ }
+}
diff --git a/packages/ibkr/src/reader.ts b/packages/ibkr/src/reader.ts
new file mode 100644
index 00000000..9b0bac54
--- /dev/null
+++ b/packages/ibkr/src/reader.ts
@@ -0,0 +1,54 @@
+/**
+ * Message reader — consumes incoming socket data and extracts framed messages.
+ * Mirrors: ibapi/reader.py
+ *
+ * Node.js adaptation: Python uses a background thread + queue. Here we use
+ * socket 'data' events → buffer accumulation → message extraction → callback.
+ * No threads, no queue.
+ */
+
+import { readMsg } from './comm.js'
+import type { Connection } from './connection.js'
+
+export class EReader {
+ private conn: Connection
+ private buf: Buffer = Buffer.alloc(0)
+ private onMessage: (msg: Buffer) => void
+
+ constructor(conn: Connection, onMessage: (msg: Buffer) => void) {
+ this.conn = conn
+ this.onMessage = onMessage
+ }
+
+ /**
+ * Start listening for incoming data.
+ */
+ start(): void {
+ this.conn.on('data', () => {
+ this.processData()
+ })
+ }
+
+ /**
+ * Process accumulated socket data, extracting complete messages.
+ */
+ private processData(): void {
+ // Consume whatever has accumulated in the connection buffer
+ const incoming = this.conn.consumeBuffer()
+ if (incoming.length === 0) return
+
+ this.buf = Buffer.concat([this.buf, incoming])
+
+ // Extract as many complete messages as possible
+ while (this.buf.length > 0) {
+ const [size, msg, rest] = readMsg(this.buf)
+ if (msg.length > 0) {
+ this.buf = rest
+ this.onMessage(msg)
+ } else {
+ // Incomplete message — wait for more data
+ break
+ }
+ }
+ }
+}
diff --git a/packages/ibkr/src/scanner.ts b/packages/ibkr/src/scanner.ts
new file mode 100644
index 00000000..32ad26ef
--- /dev/null
+++ b/packages/ibkr/src/scanner.ts
@@ -0,0 +1,76 @@
+/**
+ * Mirrors: ibapi/scanner.py
+ */
+
+import { UNSET_INTEGER, UNSET_DOUBLE } from './const.js'
+import type { Contract } from './contract.js'
+
+export class ScanData {
+ contract: Contract | null
+ rank: number
+ distance: string
+ benchmark: string
+ projection: string
+ legsStr: string
+ marketName: string
+
+ constructor(
+ contract: Contract | null = null,
+ rank = 0,
+ distance = '',
+ benchmark = '',
+ projection = '',
+ legsStr = '',
+ marketName = '',
+ ) {
+ this.contract = contract
+ this.rank = rank
+ this.distance = distance
+ this.benchmark = benchmark
+ this.projection = projection
+ this.legsStr = legsStr
+ this.marketName = marketName
+ }
+
+ toString(): string {
+ return (
+ `Rank: ${this.rank}, Symbol: ${this.contract?.symbol}, ` +
+ `SecType: ${this.contract?.secType}, Currency: ${this.contract?.currency}, ` +
+ `Distance: ${this.distance}, Benchmark: ${this.benchmark}, ` +
+ `Projection: ${this.projection}, Legs String: ${this.legsStr}, ` +
+ `MarketName: ${this.marketName}`
+ )
+ }
+}
+
+export const NO_ROW_NUMBER_SPECIFIED = -1
+
+export class ScannerSubscription {
+ numberOfRows: number = NO_ROW_NUMBER_SPECIFIED
+ instrument = ''
+ locationCode = ''
+ scanCode = ''
+ abovePrice: number = UNSET_DOUBLE
+ belowPrice: number = UNSET_DOUBLE
+ aboveVolume: number = UNSET_INTEGER
+ marketCapAbove: number = UNSET_DOUBLE
+ marketCapBelow: number = UNSET_DOUBLE
+ moodyRatingAbove = ''
+ moodyRatingBelow = ''
+ spRatingAbove = ''
+ spRatingBelow = ''
+ maturityDateAbove = ''
+ maturityDateBelow = ''
+ couponRateAbove: number = UNSET_DOUBLE
+ couponRateBelow: number = UNSET_DOUBLE
+ excludeConvertible = false
+ averageOptionVolumeAbove: number = UNSET_INTEGER
+ scannerSettingPairs = ''
+ stockTypeFilter = ''
+
+ toString(): string {
+ return (
+ `Instrument: ${this.instrument}, LocationCode: ${this.locationCode}, ScanCode: ${this.scanCode}`
+ )
+ }
+}
diff --git a/packages/ibkr/src/server-versions.ts b/packages/ibkr/src/server-versions.ts
new file mode 100644
index 00000000..3d0ceb03
--- /dev/null
+++ b/packages/ibkr/src/server-versions.ts
@@ -0,0 +1,167 @@
+/**
+ * Known server version gates. Each constant represents the minimum server
+ * version required to support a particular feature.
+ * Mirrors: ibapi/server_versions.py
+ */
+
+export const MIN_SERVER_VER_PTA_ORDERS = 39
+export const MIN_SERVER_VER_FUNDAMENTAL_DATA = 40
+export const MIN_SERVER_VER_DELTA_NEUTRAL = 40
+export const MIN_SERVER_VER_CONTRACT_DATA_CHAIN = 40
+export const MIN_SERVER_VER_SCALE_ORDERS2 = 40
+export const MIN_SERVER_VER_ALGO_ORDERS = 41
+export const MIN_SERVER_VER_EXECUTION_DATA_CHAIN = 42
+export const MIN_SERVER_VER_NOT_HELD = 44
+export const MIN_SERVER_VER_SEC_ID_TYPE = 45
+export const MIN_SERVER_VER_PLACE_ORDER_CONID = 46
+export const MIN_SERVER_VER_REQ_MKT_DATA_CONID = 47
+export const MIN_SERVER_VER_REQ_CALC_IMPLIED_VOLAT = 49
+export const MIN_SERVER_VER_REQ_CALC_OPTION_PRICE = 50
+export const MIN_SERVER_VER_SSHORTX_OLD = 51
+export const MIN_SERVER_VER_SSHORTX = 52
+export const MIN_SERVER_VER_REQ_GLOBAL_CANCEL = 53
+export const MIN_SERVER_VER_HEDGE_ORDERS = 54
+export const MIN_SERVER_VER_REQ_MARKET_DATA_TYPE = 55
+export const MIN_SERVER_VER_OPT_OUT_SMART_ROUTING = 56
+export const MIN_SERVER_VER_SMART_COMBO_ROUTING_PARAMS = 57
+export const MIN_SERVER_VER_DELTA_NEUTRAL_CONID = 58
+export const MIN_SERVER_VER_SCALE_ORDERS3 = 60
+export const MIN_SERVER_VER_ORDER_COMBO_LEGS_PRICE = 61
+export const MIN_SERVER_VER_TRAILING_PERCENT = 62
+export const MIN_SERVER_VER_DELTA_NEUTRAL_OPEN_CLOSE = 66
+export const MIN_SERVER_VER_POSITIONS = 67
+export const MIN_SERVER_VER_ACCOUNT_SUMMARY = 67
+export const MIN_SERVER_VER_TRADING_CLASS = 68
+export const MIN_SERVER_VER_SCALE_TABLE = 69
+export const MIN_SERVER_VER_LINKING = 70
+export const MIN_SERVER_VER_ALGO_ID = 71
+export const MIN_SERVER_VER_OPTIONAL_CAPABILITIES = 72
+export const MIN_SERVER_VER_ORDER_SOLICITED = 73
+export const MIN_SERVER_VER_LINKING_AUTH = 74
+export const MIN_SERVER_VER_PRIMARYEXCH = 75
+export const MIN_SERVER_VER_RANDOMIZE_SIZE_AND_PRICE = 76
+export const MIN_SERVER_VER_FRACTIONAL_POSITIONS = 101
+export const MIN_SERVER_VER_PEGGED_TO_BENCHMARK = 102
+export const MIN_SERVER_VER_MODELS_SUPPORT = 103
+export const MIN_SERVER_VER_SEC_DEF_OPT_PARAMS_REQ = 104
+export const MIN_SERVER_VER_EXT_OPERATOR = 105
+export const MIN_SERVER_VER_SOFT_DOLLAR_TIER = 106
+export const MIN_SERVER_VER_REQ_FAMILY_CODES = 107
+export const MIN_SERVER_VER_REQ_MATCHING_SYMBOLS = 108
+export const MIN_SERVER_VER_PAST_LIMIT = 109
+export const MIN_SERVER_VER_MD_SIZE_MULTIPLIER = 110
+export const MIN_SERVER_VER_CASH_QTY = 111
+export const MIN_SERVER_VER_REQ_MKT_DEPTH_EXCHANGES = 112
+export const MIN_SERVER_VER_TICK_NEWS = 113
+export const MIN_SERVER_VER_REQ_SMART_COMPONENTS = 114
+export const MIN_SERVER_VER_REQ_NEWS_PROVIDERS = 115
+export const MIN_SERVER_VER_REQ_NEWS_ARTICLE = 116
+export const MIN_SERVER_VER_REQ_HISTORICAL_NEWS = 117
+export const MIN_SERVER_VER_REQ_HEAD_TIMESTAMP = 118
+export const MIN_SERVER_VER_REQ_HISTOGRAM = 119
+export const MIN_SERVER_VER_SERVICE_DATA_TYPE = 120
+export const MIN_SERVER_VER_AGG_GROUP = 121
+export const MIN_SERVER_VER_UNDERLYING_INFO = 122
+export const MIN_SERVER_VER_CANCEL_HEADTIMESTAMP = 123
+export const MIN_SERVER_VER_SYNT_REALTIME_BARS = 124
+export const MIN_SERVER_VER_CFD_REROUTE = 125
+export const MIN_SERVER_VER_MARKET_RULES = 126
+export const MIN_SERVER_VER_PNL = 127
+export const MIN_SERVER_VER_NEWS_QUERY_ORIGINS = 128
+export const MIN_SERVER_VER_UNREALIZED_PNL = 129
+export const MIN_SERVER_VER_HISTORICAL_TICKS = 130
+export const MIN_SERVER_VER_MARKET_CAP_PRICE = 131
+export const MIN_SERVER_VER_PRE_OPEN_BID_ASK = 132
+export const MIN_SERVER_VER_REAL_EXPIRATION_DATE = 134
+export const MIN_SERVER_VER_REALIZED_PNL = 135
+export const MIN_SERVER_VER_LAST_LIQUIDITY = 136
+export const MIN_SERVER_VER_TICK_BY_TICK = 137
+export const MIN_SERVER_VER_DECISION_MAKER = 138
+export const MIN_SERVER_VER_MIFID_EXECUTION = 139
+export const MIN_SERVER_VER_TICK_BY_TICK_IGNORE_SIZE = 140
+export const MIN_SERVER_VER_AUTO_PRICE_FOR_HEDGE = 141
+export const MIN_SERVER_VER_WHAT_IF_EXT_FIELDS = 142
+export const MIN_SERVER_VER_SCANNER_GENERIC_OPTS = 143
+export const MIN_SERVER_VER_API_BIND_ORDER = 144
+export const MIN_SERVER_VER_ORDER_CONTAINER = 145
+export const MIN_SERVER_VER_SMART_DEPTH = 146
+export const MIN_SERVER_VER_REMOVE_NULL_ALL_CASTING = 147
+export const MIN_SERVER_VER_D_PEG_ORDERS = 148
+export const MIN_SERVER_VER_MKT_DEPTH_PRIM_EXCHANGE = 149
+export const MIN_SERVER_VER_COMPLETED_ORDERS = 150
+export const MIN_SERVER_VER_PRICE_MGMT_ALGO = 151
+export const MIN_SERVER_VER_STOCK_TYPE = 152
+export const MIN_SERVER_VER_ENCODE_MSG_ASCII7 = 153
+export const MIN_SERVER_VER_SEND_ALL_FAMILY_CODES = 154
+export const MIN_SERVER_VER_NO_DEFAULT_OPEN_CLOSE = 155
+export const MIN_SERVER_VER_PRICE_BASED_VOLATILITY = 156
+export const MIN_SERVER_VER_REPLACE_FA_END = 157
+export const MIN_SERVER_VER_DURATION = 158
+export const MIN_SERVER_VER_MARKET_DATA_IN_SHARES = 159
+export const MIN_SERVER_VER_POST_TO_ATS = 160
+export const MIN_SERVER_VER_WSHE_CALENDAR = 161
+export const MIN_SERVER_VER_AUTO_CANCEL_PARENT = 162
+export const MIN_SERVER_VER_FRACTIONAL_SIZE_SUPPORT = 163
+export const MIN_SERVER_VER_SIZE_RULES = 164
+export const MIN_SERVER_VER_HISTORICAL_SCHEDULE = 165
+export const MIN_SERVER_VER_ADVANCED_ORDER_REJECT = 166
+export const MIN_SERVER_VER_USER_INFO = 167
+export const MIN_SERVER_VER_CRYPTO_AGGREGATED_TRADES = 168
+export const MIN_SERVER_VER_MANUAL_ORDER_TIME = 169
+export const MIN_SERVER_VER_PEGBEST_PEGMID_OFFSETS = 170
+export const MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS = 171
+export const MIN_SERVER_VER_IPO_PRICES = 172
+export const MIN_SERVER_VER_WSH_EVENT_DATA_FILTERS_DATE = 173
+export const MIN_SERVER_VER_INSTRUMENT_TIMEZONE = 174
+export const MIN_SERVER_VER_HMDS_MARKET_DATA_IN_SHARES = 175
+export const MIN_SERVER_VER_BOND_ISSUERID = 176
+export const MIN_SERVER_VER_FA_PROFILE_DESUPPORT = 177
+export const MIN_SERVER_VER_PENDING_PRICE_REVISION = 178
+export const MIN_SERVER_VER_FUND_DATA_FIELDS = 179
+export const MIN_SERVER_VER_MANUAL_ORDER_TIME_EXERCISE_OPTIONS = 180
+export const MIN_SERVER_VER_OPEN_ORDER_AD_STRATEGY = 181
+export const MIN_SERVER_VER_LAST_TRADE_DATE = 182
+export const MIN_SERVER_VER_CUSTOMER_ACCOUNT = 183
+export const MIN_SERVER_VER_PROFESSIONAL_CUSTOMER = 184
+export const MIN_SERVER_VER_BOND_ACCRUED_INTEREST = 185
+export const MIN_SERVER_VER_INELIGIBILITY_REASONS = 186
+export const MIN_SERVER_VER_RFQ_FIELDS = 187
+export const MIN_SERVER_VER_BOND_TRADING_HOURS = 188
+export const MIN_SERVER_VER_INCLUDE_OVERNIGHT = 189
+export const MIN_SERVER_VER_UNDO_RFQ_FIELDS = 190
+export const MIN_SERVER_VER_PERM_ID_AS_LONG = 191
+export const MIN_SERVER_VER_CME_TAGGING_FIELDS = 192
+export const MIN_SERVER_VER_CME_TAGGING_FIELDS_IN_OPEN_ORDER = 193
+export const MIN_SERVER_VER_ERROR_TIME = 194
+export const MIN_SERVER_VER_FULL_ORDER_PREVIEW_FIELDS = 195
+export const MIN_SERVER_VER_HISTORICAL_DATA_END = 196
+export const MIN_SERVER_VER_CURRENT_TIME_IN_MILLIS = 197
+export const MIN_SERVER_VER_SUBMITTER = 198
+export const MIN_SERVER_VER_IMBALANCE_ONLY = 199
+export const MIN_SERVER_VER_PARAMETRIZED_DAYS_OF_EXECUTIONS = 200
+export const MIN_SERVER_VER_PROTOBUF = 201
+export const MIN_SERVER_VER_ZERO_STRIKE = 202
+export const MIN_SERVER_VER_PROTOBUF_PLACE_ORDER = 203
+export const MIN_SERVER_VER_PROTOBUF_COMPLETED_ORDER = 204
+export const MIN_SERVER_VER_PROTOBUF_CONTRACT_DATA = 205
+export const MIN_SERVER_VER_PROTOBUF_MARKET_DATA = 206
+export const MIN_SERVER_VER_PROTOBUF_ACCOUNTS_POSITIONS = 207
+export const MIN_SERVER_VER_PROTOBUF_HISTORICAL_DATA = 208
+export const MIN_SERVER_VER_PROTOBUF_NEWS_DATA = 209
+export const MIN_SERVER_VER_PROTOBUF_SCAN_DATA = 210
+export const MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_1 = 211
+export const MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_2 = 212
+export const MIN_SERVER_VER_PROTOBUF_REST_MESSAGES_3 = 213
+export const MIN_SERVER_VER_ADD_Z_SUFFIX_TO_UTC_DATE_TIME = 214
+export const MIN_SERVER_VER_CANCEL_CONTRACT_DATA = 215
+export const MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_1 = 216
+export const MIN_SERVER_VER_ADDITIONAL_ORDER_PARAMS_2 = 217
+export const MIN_SERVER_VER_ATTACHED_ORDERS = 218
+export const MIN_SERVER_VER_CONFIG = 219
+export const MIN_SERVER_VER_MARKET_DATA_VOLUMES_IN_SHARES = 220
+export const MIN_SERVER_VER_UPDATE_CONFIG = 221
+export const MIN_SERVER_VER_FRACTIONAL_LAST_SIZE = 222
+
+// 100+ messaging: enhanced handshake, msg length prefixes
+export const MIN_CLIENT_VER = 100
+export const MAX_CLIENT_VER = MIN_SERVER_VER_FRACTIONAL_LAST_SIZE
diff --git a/packages/ibkr/src/softdollartier.ts b/packages/ibkr/src/softdollartier.ts
new file mode 100644
index 00000000..4765808f
--- /dev/null
+++ b/packages/ibkr/src/softdollartier.ts
@@ -0,0 +1,20 @@
+/**
+ * Soft dollar tier definition.
+ * Mirrors: ibapi/softdollartier.py
+ */
+
+export class SoftDollarTier {
+ name: string
+ val: string
+ displayName: string
+
+ constructor(name = '', val = '', displayName = '') {
+ this.name = name
+ this.val = val
+ this.displayName = displayName
+ }
+
+ toString(): string {
+ return `Name: ${this.name}, Value: ${this.val}, DisplayName: ${this.displayName}`
+ }
+}
diff --git a/packages/ibkr/src/tag-value.ts b/packages/ibkr/src/tag-value.ts
new file mode 100644
index 00000000..0e5ed397
--- /dev/null
+++ b/packages/ibkr/src/tag-value.ts
@@ -0,0 +1,21 @@
+/**
+ * Simple tag-value pair used for algo parameters and misc options.
+ * Mirrors: ibapi/tag_value.py
+ */
+
+export class TagValue {
+ tag: string
+ value: string
+
+ constructor(tag?: string, value?: string) {
+ this.tag = String(tag ?? '')
+ this.value = String(value ?? '')
+ }
+
+ toString(): string {
+ // Wire format — do not change lightly!
+ return `${this.tag}=${this.value};`
+ }
+}
+
+export type TagValueList = TagValue[] | null
diff --git a/packages/ibkr/src/tick-type.ts b/packages/ibkr/src/tick-type.ts
new file mode 100644
index 00000000..f8161c80
--- /dev/null
+++ b/packages/ibkr/src/tick-type.ts
@@ -0,0 +1,124 @@
+/**
+ * Tick type constants — market data field identifiers.
+ * Mirrors: ibapi/ticktype.py
+ */
+
+export type TickType = number
+
+export const TickTypeEnum = {
+ BID_SIZE: 0,
+ BID: 1,
+ ASK: 2,
+ ASK_SIZE: 3,
+ LAST: 4,
+ LAST_SIZE: 5,
+ HIGH: 6,
+ LOW: 7,
+ VOLUME: 8,
+ CLOSE: 9,
+ BID_OPTION_COMPUTATION: 10,
+ ASK_OPTION_COMPUTATION: 11,
+ LAST_OPTION_COMPUTATION: 12,
+ MODEL_OPTION: 13,
+ OPEN: 14,
+ LOW_13_WEEK: 15,
+ HIGH_13_WEEK: 16,
+ LOW_26_WEEK: 17,
+ HIGH_26_WEEK: 18,
+ LOW_52_WEEK: 19,
+ HIGH_52_WEEK: 20,
+ AVG_VOLUME: 21,
+ OPEN_INTEREST: 22,
+ OPTION_HISTORICAL_VOL: 23,
+ OPTION_IMPLIED_VOL: 24,
+ OPTION_BID_EXCH: 25,
+ OPTION_ASK_EXCH: 26,
+ OPTION_CALL_OPEN_INTEREST: 27,
+ OPTION_PUT_OPEN_INTEREST: 28,
+ OPTION_CALL_VOLUME: 29,
+ OPTION_PUT_VOLUME: 30,
+ INDEX_FUTURE_PREMIUM: 31,
+ BID_EXCH: 32,
+ ASK_EXCH: 33,
+ AUCTION_VOLUME: 34,
+ AUCTION_PRICE: 35,
+ AUCTION_IMBALANCE: 36,
+ MARK_PRICE: 37,
+ BID_EFP_COMPUTATION: 38,
+ ASK_EFP_COMPUTATION: 39,
+ LAST_EFP_COMPUTATION: 40,
+ OPEN_EFP_COMPUTATION: 41,
+ HIGH_EFP_COMPUTATION: 42,
+ LOW_EFP_COMPUTATION: 43,
+ CLOSE_EFP_COMPUTATION: 44,
+ LAST_TIMESTAMP: 45,
+ SHORTABLE: 46,
+ FUNDAMENTAL_RATIOS: 47,
+ RT_VOLUME: 48,
+ HALTED: 49,
+ BID_YIELD: 50,
+ ASK_YIELD: 51,
+ LAST_YIELD: 52,
+ CUST_OPTION_COMPUTATION: 53,
+ TRADE_COUNT: 54,
+ TRADE_RATE: 55,
+ VOLUME_RATE: 56,
+ LAST_RTH_TRADE: 57,
+ RT_HISTORICAL_VOL: 58,
+ IB_DIVIDENDS: 59,
+ BOND_FACTOR_MULTIPLIER: 60,
+ REGULATORY_IMBALANCE: 61,
+ NEWS_TICK: 62,
+ SHORT_TERM_VOLUME_3_MIN: 63,
+ SHORT_TERM_VOLUME_5_MIN: 64,
+ SHORT_TERM_VOLUME_10_MIN: 65,
+ DELAYED_BID: 66,
+ DELAYED_ASK: 67,
+ DELAYED_LAST: 68,
+ DELAYED_BID_SIZE: 69,
+ DELAYED_ASK_SIZE: 70,
+ DELAYED_LAST_SIZE: 71,
+ DELAYED_HIGH: 72,
+ DELAYED_LOW: 73,
+ DELAYED_VOLUME: 74,
+ DELAYED_CLOSE: 75,
+ DELAYED_OPEN: 76,
+ RT_TRD_VOLUME: 77,
+ CREDITMAN_MARK_PRICE: 78,
+ CREDITMAN_SLOW_MARK_PRICE: 79,
+ DELAYED_BID_OPTION: 80,
+ DELAYED_ASK_OPTION: 81,
+ DELAYED_LAST_OPTION: 82,
+ DELAYED_MODEL_OPTION: 83,
+ LAST_EXCH: 84,
+ LAST_REG_TIME: 85,
+ FUTURES_OPEN_INTEREST: 86,
+ AVG_OPT_VOLUME: 87,
+ DELAYED_LAST_TIMESTAMP: 88,
+ SHORTABLE_SHARES: 89,
+ DELAYED_HALTED: 90,
+ REUTERS_2_MUTUAL_FUNDS: 91,
+ ETF_NAV_CLOSE: 92,
+ ETF_NAV_PRIOR_CLOSE: 93,
+ ETF_NAV_BID: 94,
+ ETF_NAV_ASK: 95,
+ ETF_NAV_LAST: 96,
+ ETF_FROZEN_NAV_LAST: 97,
+ ETF_NAV_HIGH: 98,
+ ETF_NAV_LOW: 99,
+ SOCIAL_MARKET_ANALYTICS: 100,
+ ESTIMATED_IPO_MIDPOINT: 101,
+ FINAL_IPO_LAST: 102,
+ DELAYED_YIELD_BID: 103,
+ DELAYED_YIELD_ASK: 104,
+ NOT_SET: 105,
+} as const
+
+const idx2name: Record = {}
+for (const [name, idx] of Object.entries(TickTypeEnum)) {
+ idx2name[idx] = name
+}
+
+export function tickTypeToString(tickType: number): string {
+ return idx2name[tickType] ?? `Unknown(${tickType})`
+}
diff --git a/packages/ibkr/src/utils.ts b/packages/ibkr/src/utils.ts
new file mode 100644
index 00000000..bea2f170
--- /dev/null
+++ b/packages/ibkr/src/utils.ts
@@ -0,0 +1,180 @@
+/**
+ * Collection of misc tools — field decoding, validation, formatting.
+ * Mirrors: ibapi/utils.py
+ */
+
+import Decimal from 'decimal.js'
+import {
+ UNSET_INTEGER,
+ UNSET_DOUBLE,
+ UNSET_LONG,
+ UNSET_DECIMAL,
+ DOUBLE_INFINITY,
+ INFINITY_STR,
+} from './const.js'
+
+export class BadMessage extends Error {
+ constructor(text: string) {
+ super(text)
+ this.name = 'BadMessage'
+ }
+}
+
+export class ClientException extends Error {
+ code: number
+ msg: string
+ text: string
+
+ constructor(code: number, msg: string, text: string) {
+ super(`${msg}${text}`)
+ this.name = 'ClientException'
+ this.code = code
+ this.msg = msg
+ this.text = text
+ }
+}
+
+export const SHOW_UNSET = true
+
+/**
+ * Central field decoder. Reads next field from an iterator and converts to the
+ * requested type.
+ *
+ * Python's `decode(the_type, fields, show_unset)` — we use a string discriminator
+ * instead of Python's type objects.
+ */
+export function decodeStr(fields: Iterator): string {
+ const r = fields.next()
+ if (r.done) throw new BadMessage('no more fields')
+ return r.value
+}
+
+export function decodeInt(fields: Iterator, showUnset = false): number {
+ const r = fields.next()
+ if (r.done) throw new BadMessage('no more fields')
+ const s = r.value
+ if (showUnset) {
+ if (s === null || s === undefined || s.length === 0) return UNSET_INTEGER
+ return parseInt(s, 10)
+ }
+ return parseInt(s || '0', 10)
+}
+
+export function decodeFloat(fields: Iterator, showUnset = false): number {
+ const r = fields.next()
+ if (r.done) throw new BadMessage('no more fields')
+ const s = r.value
+ if (s === INFINITY_STR) return DOUBLE_INFINITY
+ if (showUnset) {
+ if (s === null || s === undefined || s.length === 0) return UNSET_DOUBLE
+ return parseFloat(s)
+ }
+ return parseFloat(s || '0')
+}
+
+export function decodeBool(fields: Iterator): boolean {
+ const r = fields.next()
+ if (r.done) throw new BadMessage('no more fields')
+ const s = r.value
+ return parseInt(s || '0', 10) !== 0
+}
+
+export function decodeDecimal(fields: Iterator): Decimal {
+ const r = fields.next()
+ if (r.done) throw new BadMessage('no more fields')
+ const s = r.value
+ if (
+ s === null ||
+ s === undefined ||
+ s.length === 0 ||
+ s === '2147483647' ||
+ s === '9223372036854775807' ||
+ s === '1.7976931348623157E308' ||
+ s === '-9223372036854775808'
+ ) {
+ return UNSET_DECIMAL
+ }
+ return new Decimal(s)
+}
+
+export function decodeLong(fields: Iterator, showUnset = false): bigint {
+ const r = fields.next()
+ if (r.done) throw new BadMessage('no more fields')
+ const s = r.value
+ if (showUnset) {
+ if (s === null || s === undefined || s.length === 0) return UNSET_LONG
+ return BigInt(s)
+ }
+ return BigInt(s || '0')
+}
+
+// Validation helpers
+
+export function isValidFloatValue(val: number): boolean {
+ return val !== UNSET_DOUBLE
+}
+
+export function isValidIntValue(val: number): boolean {
+ return val !== UNSET_INTEGER
+}
+
+export function isValidLongValue(val: bigint): boolean {
+ return val !== UNSET_LONG
+}
+
+export function isValidDecimalValue(val: Decimal): boolean {
+ return !val.equals(UNSET_DECIMAL)
+}
+
+// Formatting helpers
+
+export function floatMaxString(val: number | null | undefined): string {
+ if (val == null) return ''
+ if (val === UNSET_DOUBLE) return ''
+ // Match Python's f"{val:.8f}".rstrip("0").rstrip(".").rstrip(",")
+ const s = val.toFixed(8)
+ return s.replace(/0+$/, '').replace(/\.$/, '').replace(/,$/, '')
+}
+
+export function longMaxString(val: bigint): string {
+ return val !== UNSET_LONG ? String(val) : ''
+}
+
+export function intMaxString(val: number): string {
+ return val !== UNSET_INTEGER ? String(val) : ''
+}
+
+export function decimalMaxString(val: Decimal): string {
+ if (val.equals(UNSET_DECIMAL)) return ''
+ return val.toFixed()
+}
+
+export function isAsciiPrintable(val: string): boolean {
+ for (let i = 0; i < val.length; i++) {
+ const c = val.charCodeAt(i)
+ if ((c >= 32 && c < 127) || c === 9 || c === 10 || c === 13) continue
+ return false
+ }
+ return true
+}
+
+export function isPegBenchOrder(orderType: string): boolean {
+ return orderType === 'PEG BENCH' || orderType === 'PEGBENCH'
+}
+
+export function isPegMidOrder(orderType: string): boolean {
+ return orderType === 'PEG MID' || orderType === 'PEGMID'
+}
+
+export function isPegBestOrder(orderType: string): boolean {
+ return orderType === 'PEG BEST' || orderType === 'PEGBEST'
+}
+
+export function currentTimeMillis(): number {
+ return Date.now()
+}
+
+export function getTimeStrFromMillis(time: number): string {
+ if (time <= 0) return ''
+ return new Date(time).toISOString()
+}
diff --git a/packages/ibkr/src/wrapper.ts b/packages/ibkr/src/wrapper.ts
new file mode 100644
index 00000000..ca1167a3
--- /dev/null
+++ b/packages/ibkr/src/wrapper.ts
@@ -0,0 +1,1148 @@
+/**
+ * Mirrors: ibapi/wrapper.py
+ *
+ * EWrapper is the callback interface that must be implemented to receive
+ * responses from TWS/IBGW. DefaultEWrapper provides no-op defaults for
+ * every method so callers can override only the callbacks they need.
+ */
+
+import type { Decimal } from 'decimal.js';
+
+import type {
+ Contract,
+ ContractDetails,
+ ContractDescription,
+ DeltaNeutralContract,
+} from './contract.js';
+import type { Order } from './order.js';
+import type { OrderState } from './order-state.js';
+import type { Execution } from './execution.js';
+import type { CommissionAndFeesReport } from './commission-and-fees-report.js';
+import type {
+ BarData,
+ RealTimeBar,
+ HistogramData,
+ NewsProvider,
+ DepthMktDataDescription,
+ SmartComponent,
+ FamilyCode,
+ PriceIncrement,
+ HistoricalTick,
+ HistoricalTickBidAsk,
+ HistoricalTickLast,
+ HistoricalSession,
+ WshEventData,
+ TickAttrib,
+ TickAttribBidAsk,
+ TickAttribLast,
+} from './common.js';
+import type { SoftDollarTier } from './softdollartier.js';
+import type { IneligibilityReason } from './ineligibility-reason.js';
+import type { TagValue } from './tag-value.js';
+import type { ScanData } from './scanner.js';
+
+// ---------------------------------------------------------------------------
+// EWrapper interface
+// ---------------------------------------------------------------------------
+
+export interface EWrapper {
+ // ── Connection & server ──────────────────────────────────────────────
+
+ error(
+ reqId: number,
+ errorTime: number,
+ errorCode: number,
+ errorString: string,
+ advancedOrderRejectJson?: string,
+ ): void;
+
+ winError(text: string, lastError: number): void;
+
+ connectAck(): void;
+
+ connectionClosed(): void;
+
+ // ── Market data ──────────────────────────────────────────────────────
+
+ marketDataType(reqId: number, marketDataType: number): void;
+
+ tickPrice(
+ reqId: number,
+ tickType: number,
+ price: number,
+ attrib: TickAttrib,
+ ): void;
+
+ tickSize(reqId: number, tickType: number, size: Decimal): void;
+
+ tickSnapshotEnd(reqId: number): void;
+
+ tickGeneric(reqId: number, tickType: number, value: number): void;
+
+ tickString(reqId: number, tickType: number, value: string): void;
+
+ tickEFP(
+ reqId: number,
+ tickType: number,
+ basisPoints: number,
+ formattedBasisPoints: string,
+ totalDividends: number,
+ holdDays: number,
+ futureLastTradeDate: string,
+ dividendImpact: number,
+ dividendsToLastTradeDate: number,
+ ): void;
+
+ tickOptionComputation(
+ reqId: number,
+ tickType: number,
+ tickAttrib: number,
+ impliedVol: number | null,
+ delta: number | null,
+ optPrice: number | null,
+ pvDividend: number | null,
+ gamma: number | null,
+ vega: number | null,
+ theta: number | null,
+ undPrice: number | null,
+ ): void;
+
+ tickReqParams(
+ tickerId: number,
+ minTick: number,
+ bboExchange: string,
+ snapshotPermissions: number,
+ ): void;
+
+ tickNews(
+ tickerId: number,
+ timeStamp: number,
+ providerCode: string,
+ articleId: string,
+ headline: string,
+ extraData: string,
+ ): void;
+
+ // ── Orders ───────────────────────────────────────────────────────────
+
+ orderStatus(
+ orderId: number,
+ status: string,
+ filled: Decimal,
+ remaining: Decimal,
+ avgFillPrice: number,
+ permId: number,
+ parentId: number,
+ lastFillPrice: number,
+ clientId: number,
+ whyHeld: string,
+ mktCapPrice: number,
+ ): void;
+
+ openOrder(
+ orderId: number,
+ contract: Contract,
+ order: Order,
+ orderState: OrderState,
+ ): void;
+
+ openOrderEnd(): void;
+
+ completedOrder(
+ contract: Contract,
+ order: Order,
+ orderState: OrderState,
+ ): void;
+
+ completedOrdersEnd(): void;
+
+ orderBound(permId: number, clientId: number, orderId: number): void;
+
+ // ── Account ──────────────────────────────────────────────────────────
+
+ updateAccountValue(
+ key: string,
+ val: string,
+ currency: string,
+ accountName: string,
+ ): void;
+
+ updatePortfolio(
+ contract: Contract,
+ position: Decimal,
+ marketPrice: number,
+ marketValue: number,
+ averageCost: number,
+ unrealizedPNL: number,
+ realizedPNL: number,
+ accountName: string,
+ ): void;
+
+ updateAccountTime(timeStamp: string): void;
+
+ accountDownloadEnd(accountName: string): void;
+
+ managedAccounts(accountsList: string): void;
+
+ accountSummary(
+ reqId: number,
+ account: string,
+ tag: string,
+ value: string,
+ currency: string,
+ ): void;
+
+ accountSummaryEnd(reqId: number): void;
+
+ accountUpdateMulti(
+ reqId: number,
+ account: string,
+ modelCode: string,
+ key: string,
+ value: string,
+ currency: string,
+ ): void;
+
+ accountUpdateMultiEnd(reqId: number): void;
+
+ // ── Positions ────────────────────────────────────────────────────────
+
+ position(
+ account: string,
+ contract: Contract,
+ position: Decimal,
+ avgCost: number,
+ ): void;
+
+ positionEnd(): void;
+
+ positionMulti(
+ reqId: number,
+ account: string,
+ modelCode: string,
+ contract: Contract,
+ pos: Decimal,
+ avgCost: number,
+ ): void;
+
+ positionMultiEnd(reqId: number): void;
+
+ // ── Contract details ─────────────────────────────────────────────────
+
+ nextValidId(orderId: number): void;
+
+ contractDetails(reqId: number, contractDetails: ContractDetails): void;
+
+ bondContractDetails(reqId: number, contractDetails: ContractDetails): void;
+
+ contractDetailsEnd(reqId: number): void;
+
+ // ── Executions ───────────────────────────────────────────────────────
+
+ execDetails(reqId: number, contract: Contract, execution: Execution): void;
+
+ execDetailsEnd(reqId: number): void;
+
+ commissionAndFeesReport(
+ commissionAndFeesReport: CommissionAndFeesReport,
+ ): void;
+
+ // ── Market depth ─────────────────────────────────────────────────────
+
+ updateMktDepth(
+ reqId: number,
+ position: number,
+ operation: number,
+ side: number,
+ price: number,
+ size: Decimal,
+ ): void;
+
+ updateMktDepthL2(
+ reqId: number,
+ position: number,
+ marketMaker: string,
+ operation: number,
+ side: number,
+ price: number,
+ size: Decimal,
+ isSmartDepth: boolean,
+ ): void;
+
+ mktDepthExchanges(
+ depthMktDataDescriptions: DepthMktDataDescription[],
+ ): void;
+
+ // ── News ─────────────────────────────────────────────────────────────
+
+ updateNewsBulletin(
+ msgId: number,
+ msgType: number,
+ newsMessage: string,
+ originExch: string,
+ ): void;
+
+ newsProviders(newsProviders: NewsProvider[]): void;
+
+ newsArticle(
+ requestId: number,
+ articleType: number,
+ articleText: string,
+ ): void;
+
+ historicalNews(
+ requestId: number,
+ time: string,
+ providerCode: string,
+ articleId: string,
+ headline: string,
+ ): void;
+
+ historicalNewsEnd(requestId: number, hasMore: boolean): void;
+
+ // ── Financial Advisor ────────────────────────────────────────────────
+
+ receiveFA(faData: number, cxml: string): void;
+
+ replaceFAEnd(reqId: number, text: string): void;
+
+ // ── Historical data ──────────────────────────────────────────────────
+
+ historicalData(reqId: number, bar: BarData): void;
+
+ historicalDataEnd(reqId: number, start: string, end: string): void;
+
+ historicalDataUpdate(reqId: number, bar: BarData): void;
+
+ historicalSchedule(
+ reqId: number,
+ startDateTime: string,
+ endDateTime: string,
+ timeZone: string,
+ sessions: HistoricalSession[],
+ ): void;
+
+ headTimestamp(reqId: number, headTimestamp: string): void;
+
+ histogramData(reqId: number, items: HistogramData[]): void;
+
+ historicalTicks(
+ reqId: number,
+ ticks: HistoricalTick[],
+ done: boolean,
+ ): void;
+
+ historicalTicksBidAsk(
+ reqId: number,
+ ticks: HistoricalTickBidAsk[],
+ done: boolean,
+ ): void;
+
+ historicalTicksLast(
+ reqId: number,
+ ticks: HistoricalTickLast[],
+ done: boolean,
+ ): void;
+
+ // ── Scanner ──────────────────────────────────────────────────────────
+
+ scannerParameters(xml: string): void;
+
+ scannerData(
+ reqId: number,
+ rank: number,
+ contractDetails: ContractDetails,
+ distance: string,
+ benchmark: string,
+ projection: string,
+ legsStr: string,
+ ): void;
+
+ scannerDataEnd(reqId: number): void;
+
+ // ── Real-time bars ───────────────────────────────────────────────────
+
+ realtimeBar(
+ reqId: number,
+ time: number,
+ open_: number,
+ high: number,
+ low: number,
+ close: number,
+ volume: Decimal,
+ wap: Decimal,
+ count: number,
+ ): void;
+
+ // ── Tick-by-tick ─────────────────────────────────────────────────────
+
+ tickByTickAllLast(
+ reqId: number,
+ tickType: number,
+ time: number,
+ price: number,
+ size: Decimal,
+ tickAttribLast: TickAttribLast,
+ exchange: string,
+ specialConditions: string,
+ ): void;
+
+ tickByTickBidAsk(
+ reqId: number,
+ time: number,
+ bidPrice: number,
+ askPrice: number,
+ bidSize: Decimal,
+ askSize: Decimal,
+ tickAttribBidAsk: TickAttribBidAsk,
+ ): void;
+
+ tickByTickMidPoint(reqId: number, time: number, midPoint: number): void;
+
+ // ── Fundamentals & misc ──────────────────────────────────────────────
+
+ currentTime(time: number): void;
+
+ currentTimeInMillis(timeInMillis: number): void;
+
+ fundamentalData(reqId: number, data: string): void;
+
+ deltaNeutralValidation(
+ reqId: number,
+ deltaNeutralContract: DeltaNeutralContract,
+ ): void;
+
+ // ── Option chains ────────────────────────────────────────────────────
+
+ securityDefinitionOptionParameter(
+ reqId: number,
+ exchange: string,
+ underlyingConId: number,
+ tradingClass: string,
+ multiplier: string,
+ expirations: Set,
+ strikes: Set,
+ ): void;
+
+ securityDefinitionOptionParameterEnd(reqId: number): void;
+
+ // ── Soft dollar tiers ────────────────────────────────────────────────
+
+ softDollarTiers(reqId: number, tiers: SoftDollarTier[]): void;
+
+ // ── Symbol / family / smart / market rules ───────────────────────────
+
+ familyCodes(familyCodes: FamilyCode[]): void;
+
+ symbolSamples(
+ reqId: number,
+ contractDescriptions: ContractDescription[],
+ ): void;
+
+ smartComponents(
+ reqId: number,
+ smartComponentMap: SmartComponent[],
+ ): void;
+
+ marketRule(marketRuleId: number, priceIncrements: PriceIncrement[]): void;
+
+ // ── PnL ──────────────────────────────────────────────────────────────
+
+ pnl(
+ reqId: number,
+ dailyPnL: number,
+ unrealizedPnL: number | null,
+ realizedPnL: number | null,
+ ): void;
+
+ pnlSingle(
+ reqId: number,
+ pos: Decimal,
+ dailyPnL: number,
+ unrealizedPnL: number | null,
+ realizedPnL: number | null,
+ value: number,
+ ): void;
+
+ // ── Reroute ──────────────────────────────────────────────────────────
+
+ rerouteMktDataReq(reqId: number, conId: number, exchange: string): void;
+
+ rerouteMktDepthReq(reqId: number, conId: number, exchange: string): void;
+
+ // ── Display groups ───────────────────────────────────────────────────
+
+ displayGroupList(reqId: number, groups: string): void;
+
+ displayGroupUpdated(reqId: number, contractInfo: string): void;
+
+ // ── Verify (deprecated) ──────────────────────────────────────────────
+
+ verifyMessageAPI(apiData: string): void;
+
+ verifyCompleted(isSuccessful: boolean, errorText: string): void;
+
+ verifyAndAuthMessageAPI(apiData: string, xyzChallange: string): void;
+
+ verifyAndAuthCompleted(isSuccessful: boolean, errorText: string): void;
+
+ // ── WSH ──────────────────────────────────────────────────────────────
+
+ wshMetaData(reqId: number, dataJson: string): void;
+
+ wshEventData(reqId: number, dataJson: string): void;
+
+ // ── User info ────────────────────────────────────────────────────────
+
+ userInfo(reqId: number, whiteBrandingId: string): void;
+
+ // ── Protobuf callbacks ───────────────────────────────────────────────
+
+ orderStatusProtoBuf(orderStatusProto: unknown): void;
+ openOrderProtoBuf(openOrderProto: unknown): void;
+ openOrdersEndProtoBuf(openOrdersEndProto: unknown): void;
+ errorProtoBuf(errorMessageProto: unknown): void;
+ executionDetailsProtoBuf(executionDetailsProto: unknown): void;
+ executionDetailsEndProtoBuf(executionDetailsProto: unknown): void;
+ completedOrderProtoBuf(completedOrderProto: unknown): void;
+ completedOrdersEndProtoBuf(completedOrdersEndProto: unknown): void;
+ orderBoundProtoBuf(orderBoundProto: unknown): void;
+ contractDataProtoBuf(contractDataProto: unknown): void;
+ bondContractDataProtoBuf(contractDataProto: unknown): void;
+ contractDataEndProtoBuf(contractDataEndProto: unknown): void;
+ tickPriceProtoBuf(tickPriceProto: unknown): void;
+ tickSizeProtoBuf(tickSizeProto: unknown): void;
+ tickOptionComputationProtoBuf(tickOptionComputationProto: unknown): void;
+ tickGenericProtoBuf(tickGenericProto: unknown): void;
+ tickStringProtoBuf(tickStringProto: unknown): void;
+ tickSnapshotEndProtoBuf(tickSnapshotEndProto: unknown): void;
+ updateMarketDepthProtoBuf(marketDepthProto: unknown): void;
+ updateMarketDepthL2ProtoBuf(marketDepthL2Proto: unknown): void;
+ updateMarketDataTypeProtoBuf(marketDataTypeProto: unknown): void;
+ tickReqParamsProtoBuf(tickReqParamsProto: unknown): void;
+ updateAccountValueProtoBuf(accountValueProto: unknown): void;
+ updatePortfolioProtoBuf(portfolioValueProto: unknown): void;
+ updateAccountTimeProtoBuf(accountUpdateTimeProto: unknown): void;
+ accountDataEndProtoBuf(accountDataEndProto: unknown): void;
+ managedAccountsProtoBuf(managedAccountsProto: unknown): void;
+ positionProtoBuf(positionProto: unknown): void;
+ positionEndProtoBuf(positionEndProto: unknown): void;
+ accountSummaryProtoBuf(accountSummaryProto: unknown): void;
+ accountSummaryEndProtoBuf(accountSummaryEndProto: unknown): void;
+ positionMultiProtoBuf(positionMultiProto: unknown): void;
+ positionMultiEndProtoBuf(positionMultiEndProto: unknown): void;
+ accountUpdateMultiProtoBuf(accountUpdateMultiProto: unknown): void;
+ accountUpdateMultiEndProtoBuf(accountUpdateMultiEndProto: unknown): void;
+ historicalDataProtoBuf(historicalDataProto: unknown): void;
+ historicalDataUpdateProtoBuf(historicalDataUpdateProto: unknown): void;
+ historicalDataEndProtoBuf(historicalDataEndProto: unknown): void;
+ realTimeBarTickProtoBuf(realTimeBarTickProto: unknown): void;
+ headTimestampProtoBuf(headTimestampProto: unknown): void;
+ histogramDataProtoBuf(histogramDataProto: unknown): void;
+ historicalTicksProtoBuf(historicalTicksProto: unknown): void;
+ historicalTicksBidAskProtoBuf(historicalTicksBidAskProto: unknown): void;
+ historicalTicksLastProtoBuf(historicalTicksLastProto: unknown): void;
+ tickByTickDataProtoBuf(tickByTickDataProto: unknown): void;
+ updateNewsBulletinProtoBuf(newsBulletinProto: unknown): void;
+ newsArticleProtoBuf(newsArticleProto: unknown): void;
+ newsProvidersProtoBuf(newsProvidersProto: unknown): void;
+ historicalNewsProtoBuf(historicalNewsProto: unknown): void;
+ historicalNewsEndProtoBuf(historicalNewsEndProto: unknown): void;
+ wshMetaDataProtoBuf(wshMetaDataProto: unknown): void;
+ wshEventDataProtoBuf(wshEventDataProto: unknown): void;
+ tickNewsProtoBuf(tickNewsProto: unknown): void;
+ scannerParametersProtoBuf(scannerParametersProto: unknown): void;
+ scannerDataProtoBuf(scannerDataProto: unknown): void;
+ fundamentalsDataProtoBuf(fundamentalsDataProto: unknown): void;
+ pnlProtoBuf(pnlProto: unknown): void;
+ pnlSingleProtoBuf(pnlSingleProto: unknown): void;
+ receiveFAProtoBuf(receiveFAProto: unknown): void;
+ replaceFAEndProtoBuf(replaceFAEndProto: unknown): void;
+ commissionAndFeesReportProtoBuf(commissionAndFeesReportProto: unknown): void;
+ historicalScheduleProtoBuf(historicalScheduleProto: unknown): void;
+ rerouteMarketDataRequestProtoBuf(rerouteMarketDataRequestProto: unknown): void;
+ rerouteMarketDepthRequestProtoBuf(rerouteMarketDepthRequestProto: unknown): void;
+ secDefOptParameterProtoBuf(secDefOptParameterProto: unknown): void;
+ secDefOptParameterEndProtoBuf(secDefOptParameterEndProto: unknown): void;
+ softDollarTiersProtoBuf(softDollarTiersProto: unknown): void;
+ familyCodesProtoBuf(familyCodesProto: unknown): void;
+ symbolSamplesProtoBuf(symbolSamplesProto: unknown): void;
+ smartComponentsProtoBuf(smartComponentsProto: unknown): void;
+ marketRuleProtoBuf(marketRuleProto: unknown): void;
+ userInfoProtoBuf(userInfoProto: unknown): void;
+ nextValidIdProtoBuf(nextValidIdProto: unknown): void;
+ currentTimeProtoBuf(currentTimeProto: unknown): void;
+ currentTimeInMillisProtoBuf(currentTimeInMillisProto: unknown): void;
+ verifyMessageApiProtoBuf(verifyMessageApiProto: unknown): void;
+ verifyCompletedProtoBuf(verifyCompletedProto: unknown): void;
+ displayGroupListProtoBuf(displayGroupListProto: unknown): void;
+ displayGroupUpdatedProtoBuf(displayGroupUpdatedProto: unknown): void;
+ marketDepthExchangesProtoBuf(marketDepthExchangesProto: unknown): void;
+ configResponseProtoBuf(configResponseProto: unknown): void;
+ updateConfigResponseProtoBuf(updateConfigResponseProto: unknown): void;
+}
+
+// ---------------------------------------------------------------------------
+// DefaultEWrapper — no-op implementation
+// ---------------------------------------------------------------------------
+
+/* eslint-disable @typescript-eslint/no-unused-vars */
+
+export class DefaultEWrapper implements EWrapper {
+ // ── Connection & server ──────────────────────────────────────────────
+
+ error(
+ _reqId: number,
+ _errorTime: number,
+ _errorCode: number,
+ _errorString: string,
+ _advancedOrderRejectJson?: string,
+ ): void {}
+
+ winError(_text: string, _lastError: number): void {}
+
+ connectAck(): void {}
+
+ connectionClosed(): void {}
+
+ // ── Market data ──────────────────────────────────────────────────────
+
+ marketDataType(_reqId: number, _marketDataType: number): void {}
+
+ tickPrice(
+ _reqId: number,
+ _tickType: number,
+ _price: number,
+ _attrib: TickAttrib,
+ ): void {}
+
+ tickSize(_reqId: number, _tickType: number, _size: Decimal): void {}
+
+ tickSnapshotEnd(_reqId: number): void {}
+
+ tickGeneric(_reqId: number, _tickType: number, _value: number): void {}
+
+ tickString(_reqId: number, _tickType: number, _value: string): void {}
+
+ tickEFP(
+ _reqId: number,
+ _tickType: number,
+ _basisPoints: number,
+ _formattedBasisPoints: string,
+ _totalDividends: number,
+ _holdDays: number,
+ _futureLastTradeDate: string,
+ _dividendImpact: number,
+ _dividendsToLastTradeDate: number,
+ ): void {}
+
+ tickOptionComputation(
+ _reqId: number,
+ _tickType: number,
+ _tickAttrib: number,
+ _impliedVol: number | null,
+ _delta: number | null,
+ _optPrice: number | null,
+ _pvDividend: number | null,
+ _gamma: number | null,
+ _vega: number | null,
+ _theta: number | null,
+ _undPrice: number | null,
+ ): void {}
+
+ tickReqParams(
+ _tickerId: number,
+ _minTick: number,
+ _bboExchange: string,
+ _snapshotPermissions: number,
+ ): void {}
+
+ tickNews(
+ _tickerId: number,
+ _timeStamp: number,
+ _providerCode: string,
+ _articleId: string,
+ _headline: string,
+ _extraData: string,
+ ): void {}
+
+ // ── Orders ───────────────────────────────────────────────────────────
+
+ orderStatus(
+ _orderId: number,
+ _status: string,
+ _filled: Decimal,
+ _remaining: Decimal,
+ _avgFillPrice: number,
+ _permId: number,
+ _parentId: number,
+ _lastFillPrice: number,
+ _clientId: number,
+ _whyHeld: string,
+ _mktCapPrice: number,
+ ): void {}
+
+ openOrder(
+ _orderId: number,
+ _contract: Contract,
+ _order: Order,
+ _orderState: OrderState,
+ ): void {}
+
+ openOrderEnd(): void {}
+
+ completedOrder(
+ _contract: Contract,
+ _order: Order,
+ _orderState: OrderState,
+ ): void {}
+
+ completedOrdersEnd(): void {}
+
+ orderBound(_permId: number, _clientId: number, _orderId: number): void {}
+
+ // ── Account ──────────────────────────────────────────────────────────
+
+ updateAccountValue(
+ _key: string,
+ _val: string,
+ _currency: string,
+ _accountName: string,
+ ): void {}
+
+ updatePortfolio(
+ _contract: Contract,
+ _position: Decimal,
+ _marketPrice: number,
+ _marketValue: number,
+ _averageCost: number,
+ _unrealizedPNL: number,
+ _realizedPNL: number,
+ _accountName: string,
+ ): void {}
+
+ updateAccountTime(_timeStamp: string): void {}
+
+ accountDownloadEnd(_accountName: string): void {}
+
+ managedAccounts(_accountsList: string): void {}
+
+ accountSummary(
+ _reqId: number,
+ _account: string,
+ _tag: string,
+ _value: string,
+ _currency: string,
+ ): void {}
+
+ accountSummaryEnd(_reqId: number): void {}
+
+ accountUpdateMulti(
+ _reqId: number,
+ _account: string,
+ _modelCode: string,
+ _key: string,
+ _value: string,
+ _currency: string,
+ ): void {}
+
+ accountUpdateMultiEnd(_reqId: number): void {}
+
+ // ── Positions ────────────────────────────────────────────────────────
+
+ position(
+ _account: string,
+ _contract: Contract,
+ _position: Decimal,
+ _avgCost: number,
+ ): void {}
+
+ positionEnd(): void {}
+
+ positionMulti(
+ _reqId: number,
+ _account: string,
+ _modelCode: string,
+ _contract: Contract,
+ _pos: Decimal,
+ _avgCost: number,
+ ): void {}
+
+ positionMultiEnd(_reqId: number): void {}
+
+ // ── Contract details ─────────────────────────────────────────────────
+
+ nextValidId(_orderId: number): void {}
+
+ contractDetails(_reqId: number, _contractDetails: ContractDetails): void {}
+
+ bondContractDetails(
+ _reqId: number,
+ _contractDetails: ContractDetails,
+ ): void {}
+
+ contractDetailsEnd(_reqId: number): void {}
+
+ // ── Executions ───────────────────────────────────────────────────────
+
+ execDetails(
+ _reqId: number,
+ _contract: Contract,
+ _execution: Execution,
+ ): void {}
+
+ execDetailsEnd(_reqId: number): void {}
+
+ commissionAndFeesReport(
+ _commissionAndFeesReport: CommissionAndFeesReport,
+ ): void {}
+
+ // ── Market depth ─────────────────────────────────────────────────────
+
+ updateMktDepth(
+ _reqId: number,
+ _position: number,
+ _operation: number,
+ _side: number,
+ _price: number,
+ _size: Decimal,
+ ): void {}
+
+ updateMktDepthL2(
+ _reqId: number,
+ _position: number,
+ _marketMaker: string,
+ _operation: number,
+ _side: number,
+ _price: number,
+ _size: Decimal,
+ _isSmartDepth: boolean,
+ ): void {}
+
+ mktDepthExchanges(
+ _depthMktDataDescriptions: DepthMktDataDescription[],
+ ): void {}
+
+ // ── News ─────────────────────────────────────────────────────────────
+
+ updateNewsBulletin(
+ _msgId: number,
+ _msgType: number,
+ _newsMessage: string,
+ _originExch: string,
+ ): void {}
+
+ newsProviders(_newsProviders: NewsProvider[]): void {}
+
+ newsArticle(
+ _requestId: number,
+ _articleType: number,
+ _articleText: string,
+ ): void {}
+
+ historicalNews(
+ _requestId: number,
+ _time: string,
+ _providerCode: string,
+ _articleId: string,
+ _headline: string,
+ ): void {}
+
+ historicalNewsEnd(_requestId: number, _hasMore: boolean): void {}
+
+ // ── Financial Advisor ────────────────────────────────────────────────
+
+ receiveFA(_faData: number, _cxml: string): void {}
+
+ replaceFAEnd(_reqId: number, _text: string): void {}
+
+ // ── Historical data ──────────────────────────────────────────────────
+
+ historicalData(_reqId: number, _bar: BarData): void {}
+
+ historicalDataEnd(_reqId: number, _start: string, _end: string): void {}
+
+ historicalDataUpdate(_reqId: number, _bar: BarData): void {}
+
+ historicalSchedule(
+ _reqId: number,
+ _startDateTime: string,
+ _endDateTime: string,
+ _timeZone: string,
+ _sessions: HistoricalSession[],
+ ): void {}
+
+ headTimestamp(_reqId: number, _headTimestamp: string): void {}
+
+ histogramData(_reqId: number, _items: HistogramData[]): void {}
+
+ historicalTicks(
+ _reqId: number,
+ _ticks: HistoricalTick[],
+ _done: boolean,
+ ): void {}
+
+ historicalTicksBidAsk(
+ _reqId: number,
+ _ticks: HistoricalTickBidAsk[],
+ _done: boolean,
+ ): void {}
+
+ historicalTicksLast(
+ _reqId: number,
+ _ticks: HistoricalTickLast[],
+ _done: boolean,
+ ): void {}
+
+ // ── Scanner ──────────────────────────────────────────────────────────
+
+ scannerParameters(_xml: string): void {}
+
+ scannerData(
+ _reqId: number,
+ _rank: number,
+ _contractDetails: ContractDetails,
+ _distance: string,
+ _benchmark: string,
+ _projection: string,
+ _legsStr: string,
+ ): void {}
+
+ scannerDataEnd(_reqId: number): void {}
+
+ // ── Real-time bars ───────────────────────────────────────────────────
+
+ realtimeBar(
+ _reqId: number,
+ _time: number,
+ _open_: number,
+ _high: number,
+ _low: number,
+ _close: number,
+ _volume: Decimal,
+ _wap: Decimal,
+ _count: number,
+ ): void {}
+
+ // ── Tick-by-tick ─────────────────────────────────────────────────────
+
+ tickByTickAllLast(
+ _reqId: number,
+ _tickType: number,
+ _time: number,
+ _price: number,
+ _size: Decimal,
+ _tickAttribLast: TickAttribLast,
+ _exchange: string,
+ _specialConditions: string,
+ ): void {}
+
+ tickByTickBidAsk(
+ _reqId: number,
+ _time: number,
+ _bidPrice: number,
+ _askPrice: number,
+ _bidSize: Decimal,
+ _askSize: Decimal,
+ _tickAttribBidAsk: TickAttribBidAsk,
+ ): void {}
+
+ tickByTickMidPoint(
+ _reqId: number,
+ _time: number,
+ _midPoint: number,
+ ): void {}
+
+ // ── Fundamentals & misc ──────────────────────────────────────────────
+
+ currentTime(_time: number): void {}
+
+ currentTimeInMillis(_timeInMillis: number): void {}
+
+ fundamentalData(_reqId: number, _data: string): void {}
+
+ deltaNeutralValidation(
+ _reqId: number,
+ _deltaNeutralContract: DeltaNeutralContract,
+ ): void {}
+
+ // ── Option chains ────────────────────────────────────────────────────
+
+ securityDefinitionOptionParameter(
+ _reqId: number,
+ _exchange: string,
+ _underlyingConId: number,
+ _tradingClass: string,
+ _multiplier: string,
+ _expirations: Set,
+ _strikes: Set,
+ ): void {}
+
+ securityDefinitionOptionParameterEnd(_reqId: number): void {}
+
+ // ── Soft dollar tiers ────────────────────────────────────────────────
+
+ softDollarTiers(_reqId: number, _tiers: SoftDollarTier[]): void {}
+
+ // ── Symbol / family / smart / market rules ───────────────────────────
+
+ familyCodes(_familyCodes: FamilyCode[]): void {}
+
+ symbolSamples(
+ _reqId: number,
+ _contractDescriptions: ContractDescription[],
+ ): void {}
+
+ smartComponents(
+ _reqId: number,
+ _smartComponentMap: SmartComponent[],
+ ): void {}
+
+ marketRule(
+ _marketRuleId: number,
+ _priceIncrements: PriceIncrement[],
+ ): void {}
+
+ // ── PnL ──────────────────────────────────────────────────────────────
+
+ pnl(
+ _reqId: number,
+ _dailyPnL: number,
+ _unrealizedPnL: number | null,
+ _realizedPnL: number | null,
+ ): void {}
+
+ pnlSingle(
+ _reqId: number,
+ _pos: Decimal,
+ _dailyPnL: number,
+ _unrealizedPnL: number | null,
+ _realizedPnL: number | null,
+ _value: number,
+ ): void {}
+
+ // ── Reroute ──────────────────────────────────────────────────────────
+
+ rerouteMktDataReq(
+ _reqId: number,
+ _conId: number,
+ _exchange: string,
+ ): void {}
+
+ rerouteMktDepthReq(
+ _reqId: number,
+ _conId: number,
+ _exchange: string,
+ ): void {}
+
+ // ── Display groups ───────────────────────────────────────────────────
+
+ displayGroupList(_reqId: number, _groups: string): void {}
+
+ displayGroupUpdated(_reqId: number, _contractInfo: string): void {}
+
+ // ── Verify (deprecated) ──────────────────────────────────────────────
+
+ verifyMessageAPI(_apiData: string): void {}
+
+ verifyCompleted(_isSuccessful: boolean, _errorText: string): void {}
+
+ verifyAndAuthMessageAPI(_apiData: string, _xyzChallange: string): void {}
+
+ verifyAndAuthCompleted(_isSuccessful: boolean, _errorText: string): void {}
+
+ // ── WSH ──────────────────────────────────────────────────────────────
+
+ wshMetaData(_reqId: number, _dataJson: string): void {}
+
+ wshEventData(_reqId: number, _dataJson: string): void {}
+
+ // ── User info ────────────────────────────────────────────────────────
+
+ userInfo(_reqId: number, _whiteBrandingId: string): void {}
+
+ // ── Protobuf callbacks ───────────────────────────────────────────────
+
+ orderStatusProtoBuf(_orderStatusProto: unknown): void {}
+ openOrderProtoBuf(_openOrderProto: unknown): void {}
+ openOrdersEndProtoBuf(_openOrdersEndProto: unknown): void {}
+ errorProtoBuf(_errorMessageProto: unknown): void {}
+ executionDetailsProtoBuf(_executionDetailsProto: unknown): void {}
+ executionDetailsEndProtoBuf(_executionDetailsProto: unknown): void {}
+ completedOrderProtoBuf(_completedOrderProto: unknown): void {}
+ completedOrdersEndProtoBuf(_completedOrdersEndProto: unknown): void {}
+ orderBoundProtoBuf(_orderBoundProto: unknown): void {}
+ contractDataProtoBuf(_contractDataProto: unknown): void {}
+ bondContractDataProtoBuf(_contractDataProto: unknown): void {}
+ contractDataEndProtoBuf(_contractDataEndProto: unknown): void {}
+ tickPriceProtoBuf(_tickPriceProto: unknown): void {}
+ tickSizeProtoBuf(_tickSizeProto: unknown): void {}
+ tickOptionComputationProtoBuf(_tickOptionComputationProto: unknown): void {}
+ tickGenericProtoBuf(_tickGenericProto: unknown): void {}
+ tickStringProtoBuf(_tickStringProto: unknown): void {}
+ tickSnapshotEndProtoBuf(_tickSnapshotEndProto: unknown): void {}
+ updateMarketDepthProtoBuf(_marketDepthProto: unknown): void {}
+ updateMarketDepthL2ProtoBuf(_marketDepthL2Proto: unknown): void {}
+ updateMarketDataTypeProtoBuf(_marketDataTypeProto: unknown): void {}
+ tickReqParamsProtoBuf(_tickReqParamsProto: unknown): void {}
+ updateAccountValueProtoBuf(_accountValueProto: unknown): void {}
+ updatePortfolioProtoBuf(_portfolioValueProto: unknown): void {}
+ updateAccountTimeProtoBuf(_accountUpdateTimeProto: unknown): void {}
+ accountDataEndProtoBuf(_accountDataEndProto: unknown): void {}
+ managedAccountsProtoBuf(_managedAccountsProto: unknown): void {}
+ positionProtoBuf(_positionProto: unknown): void {}
+ positionEndProtoBuf(_positionEndProto: unknown): void {}
+ accountSummaryProtoBuf(_accountSummaryProto: unknown): void {}
+ accountSummaryEndProtoBuf(_accountSummaryEndProto: unknown): void {}
+ positionMultiProtoBuf(_positionMultiProto: unknown): void {}
+ positionMultiEndProtoBuf(_positionMultiEndProto: unknown): void {}
+ accountUpdateMultiProtoBuf(_accountUpdateMultiProto: unknown): void {}
+ accountUpdateMultiEndProtoBuf(_accountUpdateMultiEndProto: unknown): void {}
+ historicalDataProtoBuf(_historicalDataProto: unknown): void {}
+ historicalDataUpdateProtoBuf(_historicalDataUpdateProto: unknown): void {}
+ historicalDataEndProtoBuf(_historicalDataEndProto: unknown): void {}
+ realTimeBarTickProtoBuf(_realTimeBarTickProto: unknown): void {}
+ headTimestampProtoBuf(_headTimestampProto: unknown): void {}
+ histogramDataProtoBuf(_histogramDataProto: unknown): void {}
+ historicalTicksProtoBuf(_historicalTicksProto: unknown): void {}
+ historicalTicksBidAskProtoBuf(_historicalTicksBidAskProto: unknown): void {}
+ historicalTicksLastProtoBuf(_historicalTicksLastProto: unknown): void {}
+ tickByTickDataProtoBuf(_tickByTickDataProto: unknown): void {}
+ updateNewsBulletinProtoBuf(_newsBulletinProto: unknown): void {}
+ newsArticleProtoBuf(_newsArticleProto: unknown): void {}
+ newsProvidersProtoBuf(_newsProvidersProto: unknown): void {}
+ historicalNewsProtoBuf(_historicalNewsProto: unknown): void {}
+ historicalNewsEndProtoBuf(_historicalNewsEndProto: unknown): void {}
+ wshMetaDataProtoBuf(_wshMetaDataProto: unknown): void {}
+ wshEventDataProtoBuf(_wshEventDataProto: unknown): void {}
+ tickNewsProtoBuf(_tickNewsProto: unknown): void {}
+ scannerParametersProtoBuf(_scannerParametersProto: unknown): void {}
+ scannerDataProtoBuf(_scannerDataProto: unknown): void {}
+ fundamentalsDataProtoBuf(_fundamentalsDataProto: unknown): void {}
+ pnlProtoBuf(_pnlProto: unknown): void {}
+ pnlSingleProtoBuf(_pnlSingleProto: unknown): void {}
+ receiveFAProtoBuf(_receiveFAProto: unknown): void {}
+ replaceFAEndProtoBuf(_replaceFAEndProto: unknown): void {}
+ commissionAndFeesReportProtoBuf(_commissionAndFeesReportProto: unknown): void {}
+ historicalScheduleProtoBuf(_historicalScheduleProto: unknown): void {}
+ rerouteMarketDataRequestProtoBuf(_rerouteMarketDataRequestProto: unknown): void {}
+ rerouteMarketDepthRequestProtoBuf(_rerouteMarketDepthRequestProto: unknown): void {}
+ secDefOptParameterProtoBuf(_secDefOptParameterProto: unknown): void {}
+ secDefOptParameterEndProtoBuf(_secDefOptParameterEndProto: unknown): void {}
+ softDollarTiersProtoBuf(_softDollarTiersProto: unknown): void {}
+ familyCodesProtoBuf(_familyCodesProto: unknown): void {}
+ symbolSamplesProtoBuf(_symbolSamplesProto: unknown): void {}
+ smartComponentsProtoBuf(_smartComponentsProto: unknown): void {}
+ marketRuleProtoBuf(_marketRuleProto: unknown): void {}
+ userInfoProtoBuf(_userInfoProto: unknown): void {}
+ nextValidIdProtoBuf(_nextValidIdProto: unknown): void {}
+ currentTimeProtoBuf(_currentTimeProto: unknown): void {}
+ currentTimeInMillisProtoBuf(_currentTimeInMillisProto: unknown): void {}
+ verifyMessageApiProtoBuf(_verifyMessageApiProto: unknown): void {}
+ verifyCompletedProtoBuf(_verifyCompletedProto: unknown): void {}
+ displayGroupListProtoBuf(_displayGroupListProto: unknown): void {}
+ displayGroupUpdatedProtoBuf(_displayGroupUpdatedProto: unknown): void {}
+ marketDepthExchangesProtoBuf(_marketDepthExchangesProto: unknown): void {}
+ configResponseProtoBuf(_configResponseProto: unknown): void {}
+ updateConfigResponseProtoBuf(_updateConfigResponseProto: unknown): void {}
+}
diff --git a/packages/ibkr/tests/account-summary-tags.spec.ts b/packages/ibkr/tests/account-summary-tags.spec.ts
new file mode 100644
index 00000000..4c4ceb44
--- /dev/null
+++ b/packages/ibkr/tests/account-summary-tags.spec.ts
@@ -0,0 +1,21 @@
+/**
+ * Mirrors: tests/test_account_summary_tags.py
+ */
+
+import { describe, it, expect } from 'vitest'
+import { AccountSummaryTags, AllTags } from '../src/account-summary-tags.js'
+
+describe('AccountSummaryTags', () => {
+ it('AllTags is a comma-separated list of all tag values', () => {
+ const tags = AllTags.split(',')
+ expect(tags.length).toBe(29)
+ expect(tags).toContain('NetLiquidation')
+ expect(tags).toContain('BuyingPower')
+ expect(tags).toContain('Leverage')
+ })
+
+ it('individual tags match their key names', () => {
+ expect(AccountSummaryTags.NetLiquidation).toBe('NetLiquidation')
+ expect(AccountSummaryTags.AccountType).toBe('AccountType')
+ })
+})
diff --git a/packages/ibkr/tests/comm.spec.ts b/packages/ibkr/tests/comm.spec.ts
new file mode 100644
index 00000000..9f980ea7
--- /dev/null
+++ b/packages/ibkr/tests/comm.spec.ts
@@ -0,0 +1,138 @@
+/**
+ * Mirrors: tests/test_comm.py
+ * Tests low-level message framing — encode/decode round-trips.
+ */
+
+import { describe, it, expect } from 'vitest'
+import { makeInitialMsg, makeField, makeFieldHandleEmpty, makeMsg, makeMsgProto, readMsg, readFields } from '../src/comm.js'
+import { UNSET_DOUBLE, UNSET_INTEGER, DOUBLE_INFINITY } from '../src/const.js'
+
+describe('comm', () => {
+
+ // --- Ported from Python test_comm.py ---
+
+ it('test_make_msg: initial msg has correct size prefix and payload', () => {
+ const text = 'ABCD'
+ const msg = makeInitialMsg(text)
+
+ // First 4 bytes are big-endian size
+ const size = msg.readUInt32BE(0)
+ expect(size).toBe(text.length)
+
+ // Rest is the payload
+ expect(msg.subarray(4).toString()).toBe(text)
+ })
+
+ it('test_make_field: field is NULL-terminated', () => {
+ const text = 'ABCD'
+ const field = makeField(text)
+
+ expect(field[field.length - 1]).toBe('\0')
+ expect(field.slice(0, -1)).toBe(text)
+ expect(field.slice(0, -1).length).toBe(text.length)
+ })
+
+ it('test_read_msg: round-trip encode → decode', () => {
+ const text = 'ABCD'
+ const msg = makeInitialMsg(text)
+
+ const [size, payload, rest] = readMsg(msg)
+
+ expect(size).toBe(text.length)
+ expect(payload.toString()).toBe(text)
+ expect(rest.length).toBe(0)
+ })
+
+ it('test_readFields: multiple fields round-trip', () => {
+ const text1 = 'ABCD'
+ const text2 = '123'
+
+ const msg = makeInitialMsg(makeField(text1) + makeField(text2))
+ const [_size, payload, _rest] = readMsg(msg)
+ const fields = readFields(payload)
+
+ expect(fields.length).toBe(2)
+ expect(fields[0]).toBe(text1)
+ expect(fields[1]).toBe(text2)
+ })
+
+ // --- Additional tests beyond Python's coverage ---
+
+ it('makeField: bool is encoded as int', () => {
+ expect(makeField(true)).toBe('1\0')
+ expect(makeField(false)).toBe('0\0')
+ })
+
+ it('makeField: number is encoded as string', () => {
+ expect(makeField(42)).toBe('42\0')
+ expect(makeField(3.14)).toBe('3.14\0')
+ })
+
+ it('makeField: null throws', () => {
+ expect(() => makeField(null)).toThrow('Cannot send None to TWS')
+ })
+
+ it('makeFieldHandleEmpty: UNSET values become empty', () => {
+ expect(makeFieldHandleEmpty(UNSET_INTEGER)).toBe('\0')
+ expect(makeFieldHandleEmpty(UNSET_DOUBLE)).toBe('\0')
+ })
+
+ it('makeFieldHandleEmpty: INFINITY becomes "Infinity"', () => {
+ expect(makeFieldHandleEmpty(DOUBLE_INFINITY)).toBe('Infinity\0')
+ })
+
+ it('readMsg: incomplete message returns empty payload', () => {
+ // Only 2 bytes — not even a size prefix
+ const buf = Buffer.from([0x00, 0x01])
+ const [size, msg, rest] = readMsg(buf)
+ expect(size).toBe(0)
+ expect(msg.length).toBe(0)
+ expect(rest).toBe(buf)
+ })
+
+ it('readMsg: size prefix present but payload incomplete', () => {
+ // Size says 10 bytes but only 3 available
+ const buf = Buffer.alloc(7)
+ buf.writeUInt32BE(10, 0)
+ buf[4] = 0x41; buf[5] = 0x42; buf[6] = 0x43
+ const [size, msg, rest] = readMsg(buf)
+ expect(size).toBe(10)
+ expect(msg.length).toBe(0) // incomplete
+ expect(rest).toBe(buf)
+ })
+
+ it('makeMsg: text protocol (legacy, no raw int msgId)', () => {
+ const msg = makeMsg(1, false, makeField('hello'))
+ const [size, payload, rest] = readMsg(msg)
+ expect(size).toBeGreaterThan(0)
+ expect(rest.length).toBe(0)
+ // Payload starts with msgId as text field: "1\0"
+ const fields = readFields(payload)
+ expect(fields[0]).toBe('1')
+ expect(fields[1]).toBe('hello')
+ })
+
+ it('makeMsg: binary protocol (v201+, raw int msgId)', () => {
+ const msg = makeMsg(1, true, makeField('hello'))
+ const [size, payload, rest] = readMsg(msg)
+ expect(size).toBeGreaterThan(0)
+ expect(rest.length).toBe(0)
+ // Payload starts with 4-byte binary msgId
+ const msgId = payload.readUInt32BE(0)
+ expect(msgId).toBe(1)
+ const textPart = payload.subarray(4)
+ const fields = readFields(textPart)
+ expect(fields[0]).toBe('hello')
+ })
+
+ it('makeMsgProto: wraps protobuf data with msgId + length', () => {
+ const protoData = Buffer.from([0x08, 0x01]) // fake protobuf
+ const msg = makeMsgProto(49, protoData)
+ const [size, payload, rest] = readMsg(msg)
+ expect(size).toBe(4 + 2) // 4 bytes msgId + 2 bytes proto
+ expect(rest.length).toBe(0)
+ const msgId = payload.readUInt32BE(0)
+ expect(msgId).toBe(49)
+ expect(payload.subarray(4)).toEqual(protoData)
+ })
+})
diff --git a/packages/ibkr/tests/e2e/connect.e2e.spec.ts b/packages/ibkr/tests/e2e/connect.e2e.spec.ts
new file mode 100644
index 00000000..0028560e
--- /dev/null
+++ b/packages/ibkr/tests/e2e/connect.e2e.spec.ts
@@ -0,0 +1,29 @@
+/**
+ * E2E: basic TWS connection — server version, nextValidId, managedAccounts, currentTime.
+ */
+
+import { describe, it, expect, beforeAll } from 'vitest'
+import { client, available, results, waitFor } from './setup.js'
+
+describe.runIf(available)('TWS connect', () => {
+ beforeAll(async () => {
+ client.reqCurrentTime()
+ await waitFor(() => results.currentTime !== undefined)
+ })
+
+ it('connects and receives server version', () => {
+ expect(client.serverVersion()).toBeGreaterThanOrEqual(100)
+ })
+
+ it('receives nextValidId', () => {
+ expect(results.nextValidId).toBeGreaterThanOrEqual(1)
+ })
+
+ it('receives managedAccounts', () => {
+ expect(results.managedAccounts).toBeTruthy()
+ })
+
+ it('receives currentTime', () => {
+ expect(results.currentTime).toBeGreaterThan(0)
+ })
+})
diff --git a/packages/ibkr/tests/e2e/contract-details.e2e.spec.ts b/packages/ibkr/tests/e2e/contract-details.e2e.spec.ts
new file mode 100644
index 00000000..4cfb6e6f
--- /dev/null
+++ b/packages/ibkr/tests/e2e/contract-details.e2e.spec.ts
@@ -0,0 +1,46 @@
+/**
+ * E2E: reqContractDetails for AAPL.
+ */
+
+import { describe, it, expect, beforeAll } from 'vitest'
+import { Contract } from '../../src/index.js'
+import { client, available, results, waitFor } from './setup.js'
+
+const REQ_ID = 1001
+
+describe.runIf(available)('TWS reqContractDetails', () => {
+ beforeAll(async () => {
+ const contract = new Contract()
+ contract.symbol = 'AAPL'
+ contract.secType = 'STK'
+ contract.exchange = 'SMART'
+ contract.currency = 'USD'
+ client.reqContractDetails(REQ_ID, contract)
+
+ await waitFor(() => results.contractDetailsEnded.has(REQ_ID))
+ })
+
+ it('receives contract details', () => {
+ const details = results.contractDetails.get(REQ_ID)
+ expect(details).toBeDefined()
+ expect(details!.length).toBeGreaterThan(0)
+ })
+
+ it('receives contractDetailsEnd', () => {
+ expect(results.contractDetailsEnded.has(REQ_ID)).toBe(true)
+ })
+
+ it('has correct symbol and conId', () => {
+ const aapl = results.contractDetails.get(REQ_ID)![0]
+ expect(aapl.contract.symbol).toBe('AAPL')
+ expect(aapl.contract.conId).toBe(265598)
+ })
+
+ it('has APPLE INC as longName', () => {
+ expect(results.contractDetails.get(REQ_ID)![0].longName).toBe('APPLE INC')
+ })
+
+ it('has NASDAQ as primaryExchange', () => {
+ expect(results.contractDetails.get(REQ_ID)![0].contract.primaryExchange).toBe('NASDAQ')
+ })
+})
diff --git a/packages/ibkr/tests/e2e/setup.ts b/packages/ibkr/tests/e2e/setup.ts
new file mode 100644
index 00000000..c4d94d72
--- /dev/null
+++ b/packages/ibkr/tests/e2e/setup.ts
@@ -0,0 +1,101 @@
+/**
+ * Shared TWS connection for all e2e tests.
+ *
+ * Usage in test files:
+ * import { client, available, waitFor } from './setup'
+ *
+ * The connection is established once and reused across all e2e files.
+ * If TWS is not running, `available` is false and tests should skip.
+ */
+
+import { EClient, DefaultEWrapper, type ContractDetails } from '../../src/index.js'
+import { isTwsAvailable, TWS_HOST, TWS_PORT } from '../helpers/tws.js'
+
+// --- Collected results from TWS callbacks ---
+export const results = {
+ serverVersion: 0,
+ connTime: '',
+ nextValidId: undefined as number | undefined,
+ managedAccounts: undefined as string | undefined,
+ currentTime: undefined as number | undefined,
+ errors: [] as Array<{ reqId: number; code: number; msg: string }>,
+ contractDetails: new Map(),
+ contractDetailsEnded: new Set(),
+}
+
+// --- Wrapper that collects everything ---
+class E2EWrapper extends DefaultEWrapper {
+ connectAck() {
+ results.serverVersion = client.serverVersion()
+ results.connTime = client.twsConnectionTime() ?? ''
+ }
+
+ nextValidId(orderId: number) {
+ results.nextValidId = orderId
+ }
+
+ managedAccounts(list: string) {
+ results.managedAccounts = list
+ }
+
+ currentTime(time: number) {
+ results.currentTime = time
+ }
+
+ contractDetails(reqId: number, cd: ContractDetails) {
+ if (!results.contractDetails.has(reqId)) {
+ results.contractDetails.set(reqId, [])
+ }
+ results.contractDetails.get(reqId)!.push(cd)
+ }
+
+ contractDetailsEnd(reqId: number) {
+ results.contractDetailsEnded.add(reqId)
+ }
+
+ error(reqId: number, _t: number, code: number, msg: string) {
+ // 2000+ are informational (farm connections, etc.)
+ if (code < 2000) {
+ results.errors.push({ reqId, code, msg })
+ }
+ }
+}
+
+// --- Shared client instance ---
+export const client = new EClient(new E2EWrapper())
+
+// --- Connection state ---
+export const available = await isTwsAvailable()
+
+if (available) {
+ await client.connect(TWS_HOST, TWS_PORT, 0)
+ // Wait for initial messages (nextValidId, managedAccounts, etc.)
+ await sleep(2000)
+}
+
+// --- Helpers ---
+
+/** Wait for a condition to become true, with timeout. */
+export async function waitFor(
+ condition: () => boolean,
+ timeoutMs = 5000,
+ intervalMs = 100,
+): Promise {
+ const start = Date.now()
+ while (Date.now() - start < timeoutMs) {
+ if (condition()) return true
+ await sleep(intervalMs)
+ }
+ return condition()
+}
+
+export function sleep(ms: number): Promise {
+ return new Promise((r) => setTimeout(r, ms))
+}
+
+/** Cleanup — call in globalTeardown or afterAll at the suite level. */
+export function disconnect() {
+ if (client.isConnected()) {
+ client.disconnect()
+ }
+}
diff --git a/packages/ibkr/tests/helpers/tws.ts b/packages/ibkr/tests/helpers/tws.ts
new file mode 100644
index 00000000..5b54a2b5
--- /dev/null
+++ b/packages/ibkr/tests/helpers/tws.ts
@@ -0,0 +1,36 @@
+/**
+ * Helper for e2e tests — checks if TWS/IB Gateway is reachable.
+ * If not, tests in the suite are skipped instead of failing.
+ */
+
+import net from 'node:net'
+
+const TWS_HOST = process.env.TWS_HOST ?? '127.0.0.1'
+const TWS_PORT = parseInt(process.env.TWS_PORT ?? '7497', 10)
+
+export { TWS_HOST, TWS_PORT }
+
+export async function isTwsAvailable(
+ host = TWS_HOST,
+ port = TWS_PORT,
+ timeoutMs = 2000,
+): Promise {
+ return new Promise((resolve) => {
+ const socket = new net.Socket()
+ const timer = setTimeout(() => {
+ socket.destroy()
+ resolve(false)
+ }, timeoutMs)
+
+ socket.connect(port, host, () => {
+ clearTimeout(timer)
+ socket.destroy()
+ resolve(true)
+ })
+
+ socket.on('error', () => {
+ clearTimeout(timer)
+ resolve(false)
+ })
+ })
+}
diff --git a/packages/ibkr/tests/models.spec.ts b/packages/ibkr/tests/models.spec.ts
new file mode 100644
index 00000000..f21c925b
--- /dev/null
+++ b/packages/ibkr/tests/models.spec.ts
@@ -0,0 +1,83 @@
+/**
+ * Tests for data model construction and defaults.
+ */
+
+import { describe, it, expect } from 'vitest'
+import { Contract, ContractDetails, ComboLeg } from '../src/contract.js'
+import { Order } from '../src/order.js'
+import { OrderState } from '../src/order-state.js'
+import { Execution, ExecutionFilter } from '../src/execution.js'
+import { TagValue } from '../src/tag-value.js'
+import { SoftDollarTier } from '../src/softdollartier.js'
+import { UNSET_DOUBLE, UNSET_INTEGER } from '../src/const.js'
+
+describe('Contract', () => {
+ it('has sensible defaults', () => {
+ const c = new Contract()
+ expect(c.conId).toBe(0)
+ expect(c.symbol).toBe('')
+ expect(c.secType).toBe('')
+ expect(c.strike).toBe(UNSET_DOUBLE)
+ expect(c.comboLegs).toEqual([])
+ expect(c.deltaNeutralContract).toBeNull()
+ })
+
+ it('toString includes symbol', () => {
+ const c = new Contract()
+ c.symbol = 'AAPL'
+ c.secType = 'STK'
+ expect(c.toString()).toContain('AAPL')
+ })
+})
+
+describe('Order', () => {
+ it('has sensible defaults', () => {
+ const o = new Order()
+ expect(o.orderId).toBe(0)
+ expect(o.action).toBe('')
+ expect(o.orderType).toBe('')
+ expect(o.lmtPrice).toBe(UNSET_DOUBLE)
+ expect(o.auxPrice).toBe(UNSET_DOUBLE)
+ expect(o.transmit).toBe(true)
+ })
+})
+
+describe('TagValue', () => {
+ it('toString produces wire format', () => {
+ const tv = new TagValue('key', 'value')
+ expect(tv.toString()).toBe('key=value;')
+ })
+
+ it('defaults to empty strings', () => {
+ const tv = new TagValue()
+ expect(tv.tag).toBe('')
+ expect(tv.value).toBe('')
+ })
+})
+
+describe('SoftDollarTier', () => {
+ it('constructs with defaults', () => {
+ const sdt = new SoftDollarTier()
+ expect(sdt.name).toBe('')
+ expect(sdt.val).toBe('')
+ expect(sdt.displayName).toBe('')
+ })
+})
+
+describe('ComboLeg', () => {
+ it('constructs with defaults', () => {
+ const cl = new ComboLeg()
+ expect(cl.conId).toBe(0)
+ expect(cl.ratio).toBe(0)
+ expect(cl.action).toBe('')
+ })
+})
+
+describe('ExecutionFilter', () => {
+ it('constructs with defaults', () => {
+ const ef = new ExecutionFilter()
+ expect(ef.clientId).toBe(0)
+ expect(ef.acctCode).toBe('')
+ expect(ef.symbol).toBe('')
+ })
+})
diff --git a/packages/ibkr/tests/order-condition.spec.ts b/packages/ibkr/tests/order-condition.spec.ts
new file mode 100644
index 00000000..ac6af9c9
--- /dev/null
+++ b/packages/ibkr/tests/order-condition.spec.ts
@@ -0,0 +1,80 @@
+/**
+ * Mirrors: tests/test_order_conditions.py
+ */
+
+import { describe, it, expect } from 'vitest'
+import {
+ VolumeCondition,
+ PercentChangeCondition,
+ PriceCondition,
+ TimeCondition,
+ MarginCondition,
+ ExecutionCondition,
+ TriggerMethodEnum,
+ Create,
+ OrderCondition,
+} from '../src/order-condition.js'
+
+describe('OrderCondition', () => {
+ it('can construct all condition types', () => {
+ const vol = new VolumeCondition(8314, 'SMART', true, 1000000)
+ expect(vol.conId).toBe(8314)
+ expect(vol.exchange).toBe('SMART')
+ expect(vol.isMore).toBe(true)
+ expect(vol.volume).toBe(1000000)
+
+ const pct = new PercentChangeCondition(1111, 'AMEX', true, 0.25)
+ expect(pct.conId).toBe(1111)
+ expect(pct.changePercent).toBe(0.25)
+
+ const price = new PriceCondition(
+ TriggerMethodEnum.DoubleLast, 2222, 'NASDAQ', false, 4.75,
+ )
+ expect(price.triggerMethod).toBe(TriggerMethodEnum.DoubleLast)
+ expect(price.price).toBe(4.75)
+
+ const time = new TimeCondition(true, '20170101 09:30:00')
+ expect(time.time).toBe('20170101 09:30:00')
+
+ const margin = new MarginCondition(false, 200000)
+ expect(margin.percent).toBe(200000)
+ expect(margin.isMore).toBe(false)
+
+ const exec = new ExecutionCondition('STK', 'SMART', 'AMD')
+ expect(exec.secType).toBe('STK')
+ expect(exec.exchange).toBe('SMART')
+ expect(exec.symbol).toBe('AMD')
+ })
+
+ it('And/Or set conjunction correctly', () => {
+ const vol = new VolumeCondition(8314, 'SMART', true, 1000000)
+ vol.And()
+ expect(vol.isConjunctionConnection).toBe(true)
+ vol.Or()
+ expect(vol.isConjunctionConnection).toBe(false)
+ })
+
+ it('Create factory returns correct subclass', () => {
+ expect(Create(OrderCondition.Price)).toBeInstanceOf(PriceCondition)
+ expect(Create(OrderCondition.Time)).toBeInstanceOf(TimeCondition)
+ expect(Create(OrderCondition.Margin)).toBeInstanceOf(MarginCondition)
+ expect(Create(OrderCondition.Execution)).toBeInstanceOf(ExecutionCondition)
+ expect(Create(OrderCondition.Volume)).toBeInstanceOf(VolumeCondition)
+ expect(Create(OrderCondition.PercentChange)).toBeInstanceOf(PercentChangeCondition)
+ })
+
+ it('encode/decode round-trip via makeFields/decode', () => {
+ const vol = new VolumeCondition(8314, 'SMART', true, 1000000)
+ vol.And()
+ const fields = vol.makeFields()
+ expect(fields.length).toBeGreaterThan(0)
+
+ const vol2 = Create(OrderCondition.Volume) as VolumeCondition
+ vol2.decode(fields[Symbol.iterator]())
+ expect(vol2.conId).toBe(8314)
+ expect(vol2.exchange).toBe('SMART')
+ expect(vol2.isMore).toBe(true)
+ expect(vol2.volume).toBe(1000000)
+ expect(vol2.isConjunctionConnection).toBe(true)
+ })
+})
diff --git a/packages/ibkr/tests/protobuf-decode.spec.ts b/packages/ibkr/tests/protobuf-decode.spec.ts
new file mode 100644
index 00000000..aa3c32f4
--- /dev/null
+++ b/packages/ibkr/tests/protobuf-decode.spec.ts
@@ -0,0 +1,88 @@
+/**
+ * Tests for protobuf message decoding in the Decoder.
+ * These test that protobuf messages from TWS are correctly dispatched
+ * to EWrapper callbacks.
+ */
+
+import { describe, it, expect, vi } from 'vitest'
+import { Decoder, applyAllHandlers } from '../src/decoder'
+import { DefaultEWrapper } from '../src/wrapper.js'
+import { BinaryWriter } from '@bufbuild/protobuf/wire'
+import { CurrentTime } from '../src/protobuf/CurrentTime.js'
+import { NextValidId } from '../src/protobuf/NextValidId.js'
+import { ErrorMessage } from '../src/protobuf/ErrorMessage.js'
+import { ManagedAccounts } from '../src/protobuf/ManagedAccounts.js'
+import { IN } from '../src/message.js'
+
+function encodeProto(codec: { encode(msg: T, writer?: BinaryWriter): BinaryWriter }, msg: T): Buffer {
+ const bytes = codec.encode(msg).finish()
+ return Buffer.from(bytes)
+}
+
+describe('Decoder.processProtoBuf', () => {
+
+ it('decodes CurrentTime and calls wrapper.currentTime', () => {
+ const wrapper = new DefaultEWrapper()
+ const spy = vi.spyOn(wrapper, 'currentTime')
+ const decoder = new Decoder(wrapper, 222)
+ applyAllHandlers(decoder)
+
+ const buf = encodeProto(CurrentTime, { currentTime: 1710500000 })
+ decoder.processProtoBuf(buf, IN.CURRENT_TIME)
+
+ expect(spy).toHaveBeenCalledWith(1710500000)
+ })
+
+ it('decodes NextValidId and calls wrapper.nextValidId', () => {
+ const wrapper = new DefaultEWrapper()
+ const spy = vi.spyOn(wrapper, 'nextValidId')
+ const decoder = new Decoder(wrapper, 222)
+ applyAllHandlers(decoder)
+
+ const buf = encodeProto(NextValidId, { orderId: 42 })
+ decoder.processProtoBuf(buf, IN.NEXT_VALID_ID)
+
+ expect(spy).toHaveBeenCalledWith(42)
+ })
+
+ it('decodes ErrorMessage and calls wrapper.error', () => {
+ const wrapper = new DefaultEWrapper()
+ const spy = vi.spyOn(wrapper, 'error')
+ const decoder = new Decoder(wrapper, 222)
+ applyAllHandlers(decoder)
+
+ const buf = encodeProto(ErrorMessage, {
+ id: -1,
+ errorTime: 1710500000,
+ errorCode: 2104,
+ errorMsg: 'Market data farm connection is OK:usfarm.nj',
+ advancedOrderRejectJson: '',
+ })
+ decoder.processProtoBuf(buf, IN.ERR_MSG)
+
+ expect(spy).toHaveBeenCalledWith(-1, 1710500000, 2104, 'Market data farm connection is OK:usfarm.nj', '')
+ })
+
+ it('decodes ManagedAccounts and calls wrapper.managedAccounts', () => {
+ const wrapper = new DefaultEWrapper()
+ const spy = vi.spyOn(wrapper, 'managedAccounts')
+ const decoder = new Decoder(wrapper, 222)
+ applyAllHandlers(decoder)
+
+ const buf = encodeProto(ManagedAccounts, { accountsList: 'DU12345' })
+ decoder.processProtoBuf(buf, IN.MANAGED_ACCTS)
+
+ expect(spy).toHaveBeenCalledWith('DU12345')
+ })
+
+ it('logs unknown protobuf msgId without crashing', () => {
+ const wrapper = new DefaultEWrapper()
+ const decoder = new Decoder(wrapper, 222)
+ applyAllHandlers(decoder)
+
+ const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
+ decoder.processProtoBuf(Buffer.from([]), 999)
+ expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('unhandled protobuf'))
+ consoleSpy.mockRestore()
+ })
+})
diff --git a/packages/ibkr/tests/utils.spec.ts b/packages/ibkr/tests/utils.spec.ts
new file mode 100644
index 00000000..ee79d18c
--- /dev/null
+++ b/packages/ibkr/tests/utils.spec.ts
@@ -0,0 +1,127 @@
+/**
+ * Mirrors: tests/test_utils.py + additional decode tests
+ */
+
+import { describe, it, expect } from 'vitest'
+import Decimal from 'decimal.js'
+import {
+ decodeStr, decodeInt, decodeFloat, decodeBool, decodeDecimal,
+ floatMaxString, intMaxString, decimalMaxString,
+ isAsciiPrintable, BadMessage,
+} from '../src/utils.js'
+import { UNSET_DOUBLE, UNSET_INTEGER, UNSET_DECIMAL, DOUBLE_INFINITY } from '../src/const.js'
+import { TickTypeEnum, tickTypeToString } from '../src/tick-type.js'
+
+function iter(arr: string[]): Iterator {
+ return arr[Symbol.iterator]()
+}
+
+describe('decode functions', () => {
+ it('decodeStr: reads next string field', () => {
+ expect(decodeStr(iter(['hello', 'world']))).toBe('hello')
+ })
+
+ it('decodeStr: throws BadMessage when empty', () => {
+ expect(() => decodeStr(iter([]))).toThrow(BadMessage)
+ })
+
+ it('decodeInt: parses integer', () => {
+ expect(decodeInt(iter(['42']))).toBe(42)
+ })
+
+ it('decodeInt: empty string → 0 (no showUnset)', () => {
+ expect(decodeInt(iter(['']))).toBe(0)
+ })
+
+ it('decodeInt: empty string → UNSET_INTEGER (showUnset)', () => {
+ expect(decodeInt(iter(['']), true)).toBe(UNSET_INTEGER)
+ })
+
+ it('decodeFloat: parses float', () => {
+ expect(decodeFloat(iter(['3.14']))).toBeCloseTo(3.14)
+ })
+
+ it('decodeFloat: "Infinity" → DOUBLE_INFINITY', () => {
+ expect(decodeFloat(iter(['Infinity']))).toBe(DOUBLE_INFINITY)
+ })
+
+ it('decodeFloat: empty → UNSET_DOUBLE (showUnset)', () => {
+ expect(decodeFloat(iter(['']), true)).toBe(UNSET_DOUBLE)
+ })
+
+ it('decodeBool: "0" → false, "1" → true', () => {
+ expect(decodeBool(iter(['0']))).toBe(false)
+ expect(decodeBool(iter(['1']))).toBe(true)
+ })
+
+ it('decodeDecimal: parses Decimal', () => {
+ const d = decodeDecimal(iter(['123.456']))
+ expect(d.toString()).toBe('123.456')
+ })
+
+ it('decodeDecimal: sentinel values → UNSET_DECIMAL', () => {
+ expect(decodeDecimal(iter(['2147483647'])).equals(UNSET_DECIMAL)).toBe(true)
+ expect(decodeDecimal(iter(['9223372036854775807'])).equals(UNSET_DECIMAL)).toBe(true)
+ expect(decodeDecimal(iter(['1.7976931348623157E308'])).equals(UNSET_DECIMAL)).toBe(true)
+ expect(decodeDecimal(iter([''])).equals(UNSET_DECIMAL)).toBe(true)
+ })
+})
+
+describe('formatting helpers', () => {
+ it('floatMaxString: UNSET → empty', () => {
+ expect(floatMaxString(UNSET_DOUBLE)).toBe('')
+ })
+
+ it('floatMaxString: normal value → formatted', () => {
+ expect(floatMaxString(3.14)).toBe('3.14')
+ })
+
+ it('floatMaxString: null → empty', () => {
+ expect(floatMaxString(null)).toBe('')
+ })
+
+ it('intMaxString: UNSET → empty', () => {
+ expect(intMaxString(UNSET_INTEGER)).toBe('')
+ })
+
+ it('intMaxString: normal value → string', () => {
+ expect(intMaxString(42)).toBe('42')
+ })
+
+ it('decimalMaxString: UNSET → empty', () => {
+ expect(decimalMaxString(UNSET_DECIMAL)).toBe('')
+ })
+
+ it('decimalMaxString: normal value → string', () => {
+ expect(decimalMaxString(new Decimal('123.45'))).toBe('123.45')
+ })
+})
+
+describe('isAsciiPrintable', () => {
+ it('normal ASCII → true', () => {
+ expect(isAsciiPrintable('hello world')).toBe(true)
+ })
+
+ it('tabs and newlines → true', () => {
+ expect(isAsciiPrintable('hello\tworld\n')).toBe(true)
+ })
+
+ it('non-ASCII → false', () => {
+ expect(isAsciiPrintable('héllo')).toBe(false)
+ })
+})
+
+describe('TickTypeEnum', () => {
+ it('has expected values', () => {
+ expect(TickTypeEnum.BID).toBe(1)
+ expect(TickTypeEnum.ASK).toBe(2)
+ expect(TickTypeEnum.LAST).toBe(4)
+ expect(TickTypeEnum.CLOSE).toBe(9)
+ expect(TickTypeEnum.NOT_SET).toBe(105)
+ })
+
+ it('tickTypeToString resolves names', () => {
+ expect(tickTypeToString(1)).toBe('BID')
+ expect(tickTypeToString(999)).toBe('Unknown(999)')
+ })
+})
diff --git a/packages/ibkr/tsconfig.json b/packages/ibkr/tsconfig.json
new file mode 100644
index 00000000..dbf68f95
--- /dev/null
+++ b/packages/ibkr/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "ES2023",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "esModuleInterop": true,
+ "strict": true,
+ "outDir": "dist",
+ "rootDir": ".",
+ "skipLibCheck": true,
+ "resolveJsonModule": true,
+ "declaration": true,
+ "sourceMap": true,
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist", "ref", "**/*.test.ts"]
+}
diff --git a/packages/ibkr/tsup.config.ts b/packages/ibkr/tsup.config.ts
new file mode 100644
index 00000000..77a44fda
--- /dev/null
+++ b/packages/ibkr/tsup.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from 'tsup'
+
+export default defineConfig({
+ entry: ['src/index.ts'],
+ format: ['esm'],
+ dts: true,
+ clean: true,
+ sourcemap: true,
+ target: 'es2023',
+})
diff --git a/packages/ibkr/vitest.config.ts b/packages/ibkr/vitest.config.ts
new file mode 100644
index 00000000..cc881981
--- /dev/null
+++ b/packages/ibkr/vitest.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ include: ['tests/**/*.spec.ts'],
+ exclude: ['tests/**/*.e2e.spec.ts'],
+ },
+})
diff --git a/packages/ibkr/vitest.e2e.config.ts b/packages/ibkr/vitest.e2e.config.ts
new file mode 100644
index 00000000..b4e77349
--- /dev/null
+++ b/packages/ibkr/vitest.e2e.config.ts
@@ -0,0 +1,9 @@
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ include: ['tests/e2e/**/*.e2e.spec.ts'],
+ testTimeout: 15000,
+ fileParallelism: false,
+ },
+})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2c338828..3aa79efc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -118,6 +118,34 @@ importers:
specifier: ^4.0.18
version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)
+ packages/ibkr:
+ dependencies:
+ '@bufbuild/protobuf':
+ specifier: ^2.11.0
+ version: 2.11.0
+ decimal.js:
+ specifier: ^10.6.0
+ version: 10.6.0
+ protobufjs:
+ specifier: ^7.4.0
+ version: 7.5.4
+ devDependencies:
+ '@types/node':
+ specifier: ^22.13.4
+ version: 22.19.15
+ ts-proto:
+ specifier: ^2.11.5
+ version: 2.11.5
+ tsup:
+ specifier: ^8.4.0
+ version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vitest:
+ specifier: ^3.0.6
+ version: 3.2.4(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)
+
packages/opentypebb:
dependencies:
'@hono/node-server':
@@ -334,6 +362,9 @@ packages:
'@borewit/text-codec@0.2.1':
resolution: {integrity: sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==}
+ '@bufbuild/protobuf@2.11.0':
+ resolution: {integrity: sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==}
+
'@deno/shim-deno-test@0.5.0':
resolution: {integrity: sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w==}
@@ -899,6 +930,36 @@ packages:
'@pinojs/redact@0.4.0':
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
+ '@protobufjs/aspromise@1.1.2':
+ resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
+
+ '@protobufjs/base64@1.1.2':
+ resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
+
+ '@protobufjs/codegen@2.0.4':
+ resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==}
+
+ '@protobufjs/eventemitter@1.1.0':
+ resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
+
+ '@protobufjs/fetch@1.1.0':
+ resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
+
+ '@protobufjs/float@1.0.2':
+ resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
+
+ '@protobufjs/inquire@1.1.0':
+ resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==}
+
+ '@protobufjs/path@1.1.2':
+ resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
+
+ '@protobufjs/pool@1.1.0':
+ resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
+
+ '@protobufjs/utf8@1.1.0':
+ resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==}
+
'@rolldown/pluginutils@1.0.0-beta.27':
resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
@@ -1419,6 +1480,10 @@ packages:
caniuse-lite@1.0.30001778:
resolution: {integrity: sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==}
+ case-anything@2.1.13:
+ resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==}
+ engines: {node: '>=12.13'}
+
ccxt@4.5.38:
resolution: {integrity: sha512-mLNwzq/GbSExA5QxVaIjud5AlhYxKY0q48dV4IHjBaUQNThbBzsGM1DdL60ofO/A4/xoRyBSjOy/YIsAFird7g==}
engines: {node: '>=15.0.0'}
@@ -1525,6 +1590,11 @@ packages:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
+ detect-libc@1.0.3:
+ resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
+ engines: {node: '>=0.10'}
+ hasBin: true
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -1540,6 +1610,9 @@ packages:
resolution: {integrity: sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==}
engines: {node: '>=6'}
+ dprint-node@1.0.8:
+ resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==}
+
dunder-proto@1.0.1:
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
engines: {node: '>= 0.4'}
@@ -2062,6 +2135,9 @@ packages:
lodash@4.17.23:
resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==}
+ long@5.3.2:
+ resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+
loupe@3.2.1:
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
@@ -2289,6 +2365,10 @@ packages:
process-warning@5.0.0:
resolution: {integrity: sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==}
+ protobufjs@7.5.4:
+ resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
+ engines: {node: '>=12.0.0'}
+
proxy-addr@2.0.7:
resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
engines: {node: '>= 0.10'}
@@ -2620,6 +2700,16 @@ packages:
ts-nkeys@1.0.16:
resolution: {integrity: sha512-1qrhAlavbm36wtW+7NtKOgxpzl+70NTF8xlz9mEhiA5zHMlMxjj3sEVKWm3pGZhHXE0Q3ykjrj+OSRVaYw+Dqg==}
+ ts-poet@6.12.0:
+ resolution: {integrity: sha512-xo+iRNMWqyvXpFTaOAvLPA5QAWO6TZrSUs5s4Odaya3epqofBu/fMLHEWl8jPmjhA0s9sgj9sNvF1BmaQlmQkA==}
+
+ ts-proto-descriptors@2.1.0:
+ resolution: {integrity: sha512-S5EZYEQ6L9KLFfjSRpZWDIXDV/W7tAj8uW7pLsihIxyr62EAVSiKuVPwE8iWnr849Bqa53enex1jhDUcpgquzA==}
+
+ ts-proto@2.11.5:
+ resolution: {integrity: sha512-Ua2Mu92MhCkOCQgOTn00jOZaOE51JHW/Zfmf65Gtp7mOe2DxUVjKvaedayjQ0SVrblyCVSKCm2tAX/2FWgiFzQ==}
+ hasBin: true
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -3127,6 +3217,8 @@ snapshots:
'@borewit/text-codec@0.2.1': {}
+ '@bufbuild/protobuf@2.11.0': {}
+
'@deno/shim-deno-test@0.5.0': {}
'@deno/shim-deno@0.18.2':
@@ -3496,6 +3588,29 @@ snapshots:
'@pinojs/redact@0.4.0': {}
+ '@protobufjs/aspromise@1.1.2': {}
+
+ '@protobufjs/base64@1.1.2': {}
+
+ '@protobufjs/codegen@2.0.4': {}
+
+ '@protobufjs/eventemitter@1.1.0': {}
+
+ '@protobufjs/fetch@1.1.0':
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+ '@protobufjs/inquire': 1.1.0
+
+ '@protobufjs/float@1.0.2': {}
+
+ '@protobufjs/inquire@1.1.0': {}
+
+ '@protobufjs/path@1.1.2': {}
+
+ '@protobufjs/pool@1.1.0': {}
+
+ '@protobufjs/utf8@1.1.0': {}
+
'@rolldown/pluginutils@1.0.0-beta.27': {}
'@rollup/rollup-android-arm-eabi@4.57.1':
@@ -3989,6 +4104,8 @@ snapshots:
caniuse-lite@1.0.30001778: {}
+ case-anything@2.1.13: {}
+
ccxt@4.5.38:
dependencies:
ws: 8.19.0
@@ -4070,6 +4187,8 @@ snapshots:
depd@2.0.0: {}
+ detect-libc@1.0.3: {}
+
detect-libc@2.1.2: {}
doctrine@3.0.0:
@@ -4082,6 +4201,10 @@ snapshots:
dotenv@6.2.0: {}
+ dprint-node@1.0.8:
+ dependencies:
+ detect-libc: 1.0.3
+
dunder-proto@1.0.1:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -4635,6 +4758,8 @@ snapshots:
lodash@4.17.23: {}
+ long@5.3.2: {}
+
loupe@3.2.1: {}
lru-cache@5.1.1:
@@ -4827,6 +4952,21 @@ snapshots:
process-warning@5.0.0: {}
+ protobufjs@7.5.4:
+ dependencies:
+ '@protobufjs/aspromise': 1.1.2
+ '@protobufjs/base64': 1.1.2
+ '@protobufjs/codegen': 2.0.4
+ '@protobufjs/eventemitter': 1.1.0
+ '@protobufjs/fetch': 1.1.0
+ '@protobufjs/float': 1.0.2
+ '@protobufjs/inquire': 1.1.0
+ '@protobufjs/path': 1.1.2
+ '@protobufjs/pool': 1.1.0
+ '@protobufjs/utf8': 1.1.0
+ '@types/node': 25.2.3
+ long: 5.3.2
+
proxy-addr@2.0.7:
dependencies:
forwarded: 0.2.0
@@ -5191,6 +5331,21 @@ snapshots:
dependencies:
tweetnacl: 1.0.3
+ ts-poet@6.12.0:
+ dependencies:
+ dprint-node: 1.0.8
+
+ ts-proto-descriptors@2.1.0:
+ dependencies:
+ '@bufbuild/protobuf': 2.11.0
+
+ ts-proto@2.11.5:
+ dependencies:
+ '@bufbuild/protobuf': 2.11.0
+ case-anything: 2.1.13
+ ts-poet: 6.12.0
+ ts-proto-descriptors: 2.1.0
+
tslib@2.8.1:
optional: true