Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ jobs:
- name: Run Scanning
run: |
make scan
- name: Run Tests
run: |
make test

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ build/docs/mkdocs.yml
.env
*.env
.vscode
.DS_Store
.DS_Store
venv
.coverage
36 changes: 34 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: help lint scan clean
.PHONY: help lint scan clean test test-unit test-cov test-unit-cov

# Default target when just running 'make'
.DEFAULT_GOAL := help
Expand All @@ -25,8 +25,40 @@ clean: ## Clean up python cache files
find . -type f -name "*.py[co]" -delete
find . -type d -name "__pycache__" -delete

.PHONY: test
test: ## Run unit and integration tests (excludes e2e)
ifeq ($(OS),Windows_NT)
cmd /c "set PYTHONPATH=.;test && $(PYTHON) -m pytest test/unit/ test/integration/ -v"
else
PYTHONPATH=.:test $(PYTHON) -m pytest test/unit/ test/integration/ -v
endif

.PHONY: test-unit
test-unit: ## Run only unit tests
ifeq ($(OS),Windows_NT)
cmd /c "set PYTHONPATH=.;test && $(PYTHON) -m pytest test/unit/ -v"
else
PYTHONPATH=.:test $(PYTHON) -m pytest test/unit/ -v
endif

.PHONY: test-cov
test-cov: ## Run unit and integration tests with coverage report
ifeq ($(OS),Windows_NT)
cmd /c "set PYTHONPATH=.;test && $(PYTHON) -m pytest test/unit/ test/integration/ --cov=ibind --cov-report=term-missing --cov-report=html"
else
PYTHONPATH=.:test $(PYTHON) -m pytest test/unit/ test/integration/ --cov=ibind --cov-report=term-missing --cov-report=html
endif

.PHONY: test-unit-cov
test-unit-cov: ## Run unit tests with coverage report
ifeq ($(OS),Windows_NT)
cmd /c "set PYTHONPATH=.;test && $(PYTHON) -m pytest test/unit/ --cov=ibind --cov-report=term-missing --cov-report=html"
else
PYTHONPATH=.:test $(PYTHON) -m pytest test/unit/ --cov=ibind --cov-report=term-missing --cov-report=html
endif

.PHONY: check-all
check-all: lint scan format ## Run all checks (lint, scan, format)
check-all: lint scan format test ## Run all checks (lint, scan, format, test)

.PHONY: help
help: # Show help for each of the Makefile recipes.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ wrong? [Create an issue and let us know!][issues]*
</a>
</p>
<p align="center">
<a href="https://opensource.org/licenses/Apache-2.0">
<img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg"/>
</a>
<a href="https://pypi.org/project/ibind">
<img src="https://img.shields.io/pypi/pyversions/ibind.svg"/>
</a>
<a href="https://github.com/Voyz/ibind/releases">
<img src="https://img.shields.io/pypi/v/ibind?label=version"/>
</a>
<a href="https://github.com/Voyz/ibind">
<img src="https://img.shields.io/badge/coverage-68%25-green.svg"/>
</a>
</p>

IBind is an unofficial Python API client library for the [Interactive Brokers Client Portal Web API.][ibkr-docs] (recently rebranded to Web API 1.0 or CPAPI 1.0) It supports both REST and WebSocket APIs of the IBKR Web API 1.0. Now fully headless with [OAuth 1.0a][wiki-oauth1a] support.
Expand Down
111 changes: 111 additions & 0 deletions agents/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

IBind is a Python library providing REST and WebSocket clients for the Interactive Brokers Client Portal Web API (CPAPI 1.0). It supports both traditional authentication via IBeam/CP Gateway and headless OAuth 1.0a authentication.

## Core Architecture

The library is structured around two main client classes:

### IbkrClient (REST API)
- **Location**: `ibind/client/ibkr_client.py`
- **Purpose**: REST API client extending `RestClient` base class
- **Mixins**: Functionality is organized into mixins in `ibind/client/ibkr_client_mixins/`:
- `accounts_mixin.py` - Account operations
- `contract_mixin.py` - Contract/security operations
- `marketdata_mixin.py` - Market data operations
- `order_mixin.py` - Order management
- `portfolio_mixin.py` - Portfolio operations
- `scanner_mixin.py` - Market scanner
- `session_mixin.py` - Session management
- `watchlist_mixin.py` - Watchlist operations

### IbkrWsClient (WebSocket API)
- **Location**: `ibind/client/ibkr_ws_client.py`
- **Purpose**: WebSocket client for real-time data streams
- **Features**: Subscription management, queue-based data access, thread lifecycle handling

### Base Components
- `ibind/base/` - Core infrastructure classes:
- `rest_client.py` - Base REST client with retry logic, session management
- `ws_client.py` - Base WebSocket client
- `queue_controller.py` - Thread-safe queue management
- `subscription_controller.py` - WebSocket subscription handling

### Authentication
- `ibind/oauth/` - OAuth 1.0a implementation for headless authentication
- Environment variable configuration via `ibind/var.py`

## Development Commands

### Setup
```bash
# Install dependencies
make install
# OR manually:
pip install -r requirements.txt
pip install -r requirements-oauth.txt # For OAuth support
pip install -r requirements-dev.txt # For development
```

### Code Quality
```bash
make lint # Run ruff linting with auto-fix
make scan # Run bandit security checks
make check-all # Run all checks (lint, scan, format)
```

### Testing
```bash
make test # Run all tests
```

### Formatting
```bash
make format # Format code using ruff
```

### Cleanup
```bash
make clean # Remove Python cache files
```

## Key Configuration

### Linting Rules (pyproject.toml)
- Uses ruff for linting and formatting
- Line length: 150 characters
- Single quotes for strings
- Specific rule ignores for legacy code (E501, PLR2004, etc.)

### Environment Variables
Key environment variables are defined in `ibind/var.py`:
- `IBIND_ACCOUNT_ID` - IBKR account identifier
- `IBIND_REST_URL` - REST API base URL
- `IBIND_CACERT` - SSL certificate path
- `IBIND_USE_OAUTH` - Enable OAuth authentication
- `IBIND_USE_SESSION` - Use persistent HTTP sessions

## Testing Structure

Tests are organized in `test/` directory:
- `unit/` - Unit tests for individual components
- `integration/` - Integration tests with mocked IBKR responses
- `e2e/` - End-to-end tests (require live IBKR connection)

## Examples

The `examples/` directory contains comprehensive usage examples:
- `rest_*.py` - REST API examples (basic to advanced)
- `ws_*.py` - WebSocket API examples

## Important Notes

- The library supports both OAuth 1.0a (headless) and traditional CP Gateway authentication
- WebSocket client requires careful lifecycle management (start/stop, subscription handling)
- Rate limiting and parallel request handling are built into the REST client
- All API endpoints follow IBKR's REST API documentation structure
- Environment variables can be configured via `.env` files (auto-patched via `patch_dotenv()`)
7 changes: 7 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[tool:pytest]
testpaths = test
pythonpath = . test
addopts = -v --tb=short
python_files = test_*.py
python_classes = Test*
python_functions = test_*
Comment on lines +1 to +7
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been trying to use pytest (and Pydantic!) in other projects to transition myself to your camp slowly, and I think these look like they're like this by default. Is there a need to specify any of them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there's a few in here that are redundant, but others aren't, I can remove the defaults.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks! 👍

2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ruff>=0.9.4,<0.10.0
bandit>=1.8.2,<2.0.0
pytest>=7.0.0,<9.0.0
pytest-cov>=4.0.0,<6.0.0