main
md 320 lines 15.4 KB
Rendered Raw
1 # Interactive Brokers Provider
2
3 ## CURRENT STATE
4
5 The repository contains an `IBKRBrokerProvider` adapter for a read-only Interactive Brokers foundation. The intended account structure is an Individual / retail IBKR account.
6
7 Real integration status:
8
9 - Real IBKR login attempted: NO
10 - Real IBKR connection used: NO
11 - Real trades executed: NO
12 - Real account, position, cash, or market-data response validated against IBKR: NO
13
14 ## INDIVIDUAL ACCOUNT AUTH METHOD
15
16 Official IBKR documentation identifies Client Portal Gateway as the authentication path for retail and individual clients. The user authenticates directly with Interactive Brokers through the gateway login UI. The platform must never collect or store IBKR username, password, MFA, browser cookies, or raw session tokens.
17
18 Official source:
19
20 - https://www.interactivebrokers.com/docs/web-api/getting-started
21 - https://www.interactivebrokers.com/docs/web-api/authentication/cpgw/installation-authentication
22 - https://www.interactivebrokers.com/docs/web-api/authentication/cpgw/request-requirements
23 - https://www.interactivebrokers.com/docs/web-api/authentication/cpgw/limitations-of-the-client-portal-gateway
24 - https://www.interactivebrokers.com/docs/web-api/authentication/cpgw/client-portal-gateway-faq
25
26 Implementation target for Individual accounts:
27
28 - Auth method: `client-portal-gateway`
29 - Broker-service talks to a broker connector endpoint, not directly to the gateway host
30 - Browser login: required
31 - Server-side login automation: not supported by IBKR
32 - Daily reauthentication: required
33
34 ## GLOBAL CONNECTOR ARCHITECTURE
35
36 The platform is a multi-user SaaS system. A single Client Portal Gateway session must never be shared between users.
37
38 The broker path is:
39
40 Authenticated user -> broker connection -> broker service -> broker connector abstraction -> user-specific IBKR connector runtime -> IBKR Client Portal Gateway -> Interactive Brokers.
41
42 `BrokerProvider` is business-facing and broker-neutral. It exposes read-only capabilities and provider status. IBKR HTTP/gateway details live behind the `BrokerConnector` contract.
43
44 Connector metadata is persisted as safe metadata only:
45
46 - `connector_id`
47 - `user_id`
48 - `broker_type`
49 - `runtime_mode`
50 - `runtime_status`
51 - `auth_status`
52 - heartbeat/auth timestamps
53 - idle/session timeout settings
54
55 The connector schema does not persist broker passwords, MFA values, raw cookies, raw session tokens, or browser secrets. If future runtime implementations need secret material, they must use opaque secret references owned by the authenticated user.
56
57 ## RUNTIME MODES
58
59 The connector abstraction supports:
60
61 - `KUBERNETES`: platform-managed connector runtime.
62 - `LOCAL_AGENT`: user-device or local connector runtime exposing the same internal connector contract.
63
64 Broker-service must not care where the connector runs. It communicates with the configured connector service endpoint and uses authenticated user ownership checks for connector status, login, sync, and snapshot access.
65
66 IBKR states that Client Portal Gateway is intended to run locally. Therefore, this repository separates architecture capability from production deployment approval. The architecture can support Kubernetes-managed or local-agent connector runtimes, but AKS-hosted Client Portal Gateway is not marked production-approved until IBKR confirms that deployment/location model is acceptable for a global SaaS product.
67
68 ## INTERACTIVE AUTHENTICATION
69
70 The flow is:
71
72 1. User clicks Connect IBKR.
73 2. Broker-service creates a user-owned connector instance and broker connection.
74 3. The connector returns an authentication URL/state.
75 4. The user authenticates directly with IBKR.
76 5. The connector checks `GET /iserver/auth/status`.
77 6. The broker connection becomes `CONNECTED` only when `authenticated=true` and `connected=true`.
78
79 The application never asks for or stores IBKR password/MFA data.
80
81 ## OAUTH 2.0 RESTRICTION
82
83 OAuth 2.0 is not the production authentication model for this Individual IBKR integration.
84
85 Official IBKR documentation states OAuth 2.0 is for licensed Organizations, Financial Advisors, and IBrokers. It is not available to Individual account structures.
86
87 Official source:
88
89 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-2/introduction
90
91 The platform must not request or configure OAuth2 client IDs, client key IDs, private keys, public-key registration metadata, or OAuth2 secrets for the Individual IBKR path.
92
93 ## OAUTH 1.0A STATUS
94
95 OAuth 1.0a is documented by IBKR for licensed Financial Advisors, Organizations, IBrokers, and third-party services. It can access IBKR endpoints directly without the local Client Portal Gateway after registration and token/session setup.
96
97 Official sources:
98
99 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/introduction
100 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/request-requirements
101 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/first-party-oauth/registration-process
102 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/first-party-oauth/first-party-o-auth-workflow
103 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/lst/obtain-live-session-token-signature
104 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/lst/compute-live-session-token
105 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/lst/validate-live-session-token
106 - https://www.interactivebrokers.com/docs/web-api/authentication/oauth-1a/authenticated-requests
107
108 OAuth 1.0a is not selected for the Individual account implementation until IBKR eligibility and registration approval requirements are confirmed for this specific account structure and use case.
109
110 ## SESSION REQUIREMENTS
111
112 IBKR Web API sessions are two-tiered:
113
114 - An outer read-only session required to make Web API requests.
115 - A brokerage session required for `/iserver` endpoints, market data, and trading-capable functionality.
116
117 Official source:
118
119 - https://www.interactivebrokers.com/docs/web-api/authentication/sessions
120
121 Client Portal Gateway requirements:
122
123 - User must log in through a browser on the same machine as the Client Portal Gateway.
124 - API calls must be made from the same machine where the gateway was authenticated.
125 - IBKR does not support automated Client Portal Gateway authentication.
126 - Clients must reauthenticate daily.
127 - Sessions can time out without regular requests or `/tickle`.
128 - `/iserver/auth/status` reports session authentication state.
129 - `/iserver/auth/ssodh/init` initializes brokerage session when needed.
130
131 Official sources:
132
133 - https://www.interactivebrokers.com/docs/web-api/authentication/cpgw/limitations-of-the-client-portal-gateway
134 - https://www.interactivebrokers.com/docs/web-api/authentication/cpgw/client-portal-gateway-faq
135 - https://www.interactivebrokers.com/docs/web-api/authentication/faq
136 - https://www.interactivebrokers.com/docs/web-api/v1/endpoints/session/initialize-brokerage-session
137
138 ## VERIFIED READ-ONLY ENDPOINTS
139
140 ### Brokerage Session Status
141
142 - Method: `GET`
143 - Path: `/iserver/auth/status`
144 - Purpose: determine current authentication status
145 - Required auth: authenticated Client Portal Gateway session
146 - Response shape: includes `authenticated`, `connected`, `competing`, `established`, and message/status fields
147 - Verification source: https://www.interactivebrokers.com/docs/web-api/api-reference/trading/trading-session/get-brokerage-status
148
149 ### Accounts
150
151 - Method: `GET`
152 - Path: `/portfolio/accounts`
153 - Purpose: list accounts for which the user can view position and account information
154 - Required auth: authenticated Web API session
155 - Response shape: account objects including `id`, `accountId`, `displayName`, `accountAlias`, `currency`, and metadata
156 - Verification source: https://www.interactivebrokers.com/docs/web-api/trading/portfolio-and-positions/querying-your-accounts
157
158 ### Positions
159
160 - Method: `GET`
161 - Path: `/portfolio/{accountId}/positions/{pageId}`
162 - Purpose: list positions for the given account
163 - Required auth: authenticated Web API session; `/portfolio/accounts` or `/portfolio/subaccounts` must be called first
164 - Pagination: page ID starts at 0; each page returns up to 100 positions
165 - Response shape: position objects including `acctId`, `conid`, `contractDesc`, `position`, `mktPrice`, `avgCost`, `currency`, `listingExchange`, `assetClass`, and `ticker`
166 - Verification source: https://www.interactivebrokers.com/docs/web-api/v1/endpoints/portfolio/positions
167
168 ### Cash / Currency Balances
169
170 - Method: `GET`
171 - Path: `/portfolio/{accountId}/ledger`
172 - Purpose: retrieve cash balances by currency
173 - Required auth: authenticated Web API session; `/portfolio/accounts` or `/portfolio/subaccounts` must be called first
174 - Response shape: object keyed by currency, including `cashbalance`, `currency`, `settledcash`, `netliquidationvalue`, and other ledger values
175 - Verification source: https://www.interactivebrokers.com/docs/web-api/trading/portfolio-and-positions/querying-currency-balances
176
177 ### Market Data
178
179 - Method: `GET`
180 - Path: `/iserver/marketdata/snapshot`
181 - Purpose: retrieve top-of-book market data snapshots for conids and requested field tags
182 - Required auth: authenticated brokerage session and relevant market data permissions
183 - Response shape: array of market data objects keyed by numeric field tags plus fields such as `conid`, `conidEx`, `_updated`, and `server_id`
184 - Entitlement requirements: carried by the IBKR username
185 - Verification source: https://www.interactivebrokers.com/docs/web-api/trading/market-data/top-of-book-snapshots
186
187 Market data remains disabled in this platform unless explicitly enabled by verified entitlement and configuration.
188
189 ## READ-ONLY CAPABILITIES
190
191 When disabled, documentation-unverified, OAuth2-configured, or missing connector configuration, IBKR advertises no capabilities.
192
193 When explicitly enabled with the verified Individual-account Client Portal Gateway method, the current code may advertise:
194
195 - `ACCOUNTS_READ`
196 - `ACCOUNT_METADATA_READ`
197 - `PORTFOLIO_READ`
198 - `POSITIONS_READ`
199 - `CASH_READ`
200
201 `MARKET_DATA_READ` is not enabled by default.
202
203 ## NOT SUPPORTED
204
205 - Order placement
206 - Order modification
207 - Order cancellation
208 - Buy/sell actions
209 - Trade execution
210 - Browser login automation
211 - Stored broker usernames or passwords
212 - Stored OTP, MFA, CAPTCHA, raw access-token, OAuth2 private-key, or OAuth2 client secret values
213 - Shared IBKR Gateway sessions across users
214 - Broker-service direct dependency on localhost, host machine aliases, Pod IPs, or Node IPs
215
216 ## MULTI-USER IMPLICATIONS
217
218 Each authenticated application user owns their own broker connection and connector instance. Client Portal Gateway has machine/session constraints:
219
220 - A gateway session is authenticated by one IBKR username.
221 - A single IBKR username can have only one brokerage session active at a time.
222 - API calls must originate on the same machine as the authenticated gateway.
223 - Multiple application users are isolated at the application data and connector layers, and each user's real IBKR connectivity requires a separate authenticated gateway/session boundary.
224
225 The platform must not share one user's IBKR gateway session with another application user.
226
227 ## CURRENT PROVIDER STATUS
228
229 - Default: `NOT_CONFIGURED`
230 - Enabled without official documentation verification: `DOCUMENTATION_REQUIRED`
231 - Enabled with OAuth2/private_key_jwt: `DOCUMENTATION_REQUIRED` for Individual account integration
232 - Enabled with Client Portal Gateway but missing connector endpoint: `NOT_CONFIGURED`
233 - Enabled with Client Portal Gateway but unauthenticated session: `AUTHENTICATION_REQUIRED`
234 - Real provider enabled for real use: NO
235
236 ## REQUIRED BEFORE REAL CREDENTIAL USE
237
238 Before real IBKR credentials or sessions can be configured:
239
240 1. Complete the connector runtime implementation for either `KUBERNETES`, `LOCAL_AGENT`, or both.
241 2. Ensure no server-side browser automation is used.
242 3. Define how users will perform interactive browser login and daily reauthentication.
243 4. Define how the platform detects session timeout and prompts reauth safely.
244 5. Verify read-only scopes/capabilities in a controlled non-trading test plan.
245 6. Keep PRD Individual IBKR runtime disabled until IBKR approves the production connector runtime location for this SaaS use case.
246
247 ## PACKAGE AND LICENSING
248
249 Do not commit the IBKR Gateway ZIP/package or derivative redistribution artifact to source control unless redistribution rights are verified. DEV should use an external/local artifact path or an approved image build process. PRD must treat IBKR Gateway packaging as a deployment prerequisite, not an assumed right.
250
251 ## PHASE 5B DEV REAL PACKAGE VALIDATION
252
253 This validation uses the user's locally downloaded and extracted official Client Portal Gateway package. The package path is supplied at execution time only and must not be committed or baked into any image.
254
255 Package checks:
256
257 ```powershell
258 $IbkrPackage = "<LOCAL_EXTRACTED_CLIENT_PORTAL_GATEWAY_PATH>"
259 Test-Path "$IbkrPackage\bin\run.sh"
260 Test-Path "$IbkrPackage\root\conf.yaml"
261 Get-ChildItem "$IbkrPackage" | Select-Object -First 20
262 ```
263
264 DEV package injection uses a Kubernetes PVC mounted into the `ibkr-connector` pod:
265
266 ```powershell
267 kubectl create namespace ai-investment --dry-run=client -o yaml | kubectl apply -f -
268 @'
269 apiVersion: v1
270 kind: PersistentVolumeClaim
271 metadata:
272 name: ibkr-gateway-package-dev
273 spec:
274 accessModes:
275 - ReadWriteOnce
276 resources:
277 requests:
278 storage: 1Gi
279 '@ | kubectl apply -n ai-investment -f -
280 kubectl run ibkr-package-loader -n ai-investment --image=busybox:1.36 --restart=Never --command -- sh -c "mkdir -p /package && sleep 3600" --overrides '{"spec":{"containers":[{"name":"ibkr-package-loader","image":"busybox:1.36","command":["sh","-c","mkdir -p /package && sleep 3600"],"volumeMounts":[{"name":"pkg","mountPath":"/package"}]}],"volumes":[{"name":"pkg","persistentVolumeClaim":{"claimName":"ibkr-gateway-package-dev"}}]}}'
281 kubectl wait -n ai-investment --for=condition=Ready pod/ibkr-package-loader --timeout=120s
282 kubectl cp "$IbkrPackage\." ai-investment/ibkr-package-loader:/package
283 kubectl delete pod ibkr-package-loader -n ai-investment
284 ```
285
286 Deploy DEV with the external package mounted. The Gateway remains inside the connector pod and broker-service talks only to `http://ibkr-connector`:
287
288 ```powershell
289 helm upgrade --install ai-investment-platform infrastructure/helm/ai-investment-platform `
290 --namespace ai-investment --create-namespace `
291 --values infrastructure/helm/ai-investment-platform/values-dev.yaml `
292 --set ibkr.connectorBaseUrl=http://ibkr-connector `
293 --set ibkr.connectorInternalToken=dev-internal-connector-token-change-me `
294 --set ibkrConnector.gatewayPackagePath=/opt/ibkr/clientportal.gw `
295 --set ibkrConnector.gatewayBaseUrl=https://127.0.0.1:5000/v1/api `
296 --set ibkrConnector.gatewayTlsVerify=false `
297 --set ibkrConnector.loginPublicBaseUrl=http://localhost:18080 `
298 --set ibkrConnector.packageVolumeClaim=ibkr-gateway-package-dev
299 ```
300
301 Initial connector validation:
302
303 ```powershell
304 kubectl rollout status deployment/ibkr-connector -n ai-investment --timeout=300s
305 kubectl exec -n ai-investment deploy/ibkr-connector -- sh -c "ps -ef | grep '[b]in/run.sh'"
306 kubectl exec -n ai-investment deploy/ibkr-connector -- sh -c "python - <<'PY'
307 import socket
308 s=socket.create_connection(('127.0.0.1',5000),5)
309 s.close()
310 print('port 5000 listening')
311 PY"
312 ```
313
314 The user-facing login URL must be obtained through broker-service or the API gateway, not by browsing to a Pod IP or Kubernetes service DNS. For local DEV ingress the URL should start with:
315
316 ```text
317 http://localhost:18080/connector-sessions/
318 ```
319
320 Current limitation: this DEV runtime supports one active IBKR session per connector pod. Dynamic per-user Kubernetes pod orchestration is not implemented yet.