- Overview
- Getting Started
- Coding Standards
- Core Components
- Request and Response Handling
- Extending the API
- Troubleshooting
- Creating and Publishing Releases
The API is designed to provide a robust, efficient, and flexible interface for communicating with TWS (Trader Workstation) or IB Gateway. This API allows developers to build trading applications in Rust, leveraging its performance and safety features. The architecture is built around threads and channels for sending requests and responses between the client and the TWS.
The main thread handles user interactions with the API. The MessageBus runs on a dedicated thread. The MessageBus establishes the connection to TWS, sends messages from the client to TWS, and listens for and routes messages from TWS to the client via channels.
-
Install additional development tools:
- cargo-tarpaulin for code coverage analysis.
- cargo-audit for checking vulnerabilities in dependencies.
cargo install cargo-tarpaulin
cargo install cargo-audit
-
Create a fork of the repository.
-
Clone your fork and make sure tests are working:
git clone https://github.com/<your-github-username>/rust-ibapi
cd rust-ibapi
cargo test
-
Set up your development environment:
- We recommend using an IDE with Rust support, such as VS Code with the rust-analyzer extension.
- Configure your IDE to use rustfmt and clippy for code formatting and linting.
-
Make your changes.
- Ensure tests are still passing and coverage hasn't dropped:
cargo test
cargo tarpaulin -o html
- The coverage report will be saved as tarpaulin-report.html. Open it in your browser to view the coverage details.
- Submit a Pull Request
- Follow GitHub's guide on creating a pull request from a fork.
We follow the Rust API Guidelines. Please ensure your code adheres to these guidelines. Use cargo fmt
to format your code and cargo clippy
to catch common mistakes and improve your Rust code.
The MessageBus
is a crucial component of the API, running on its own dedicated thread. Its responsibilities include:
- Establishing and maintaining the connection to TWS
- Sending messages from the client to TWS
- Listening for messages from TWS
- Routing incoming messages to the appropriate client channels
Explore MessageBus implementation for more details.
The Client component runs on the main thread and provides the interface for user interactions with the API. It is responsible for:
- Encoding user requests into the format expected by TWS
- Sending requests to the MessageBus
- Receiving responses from the MessageBus via channels
- Decoding responses and presenting them to the user
Explore Client API for more details.
The API uses a combination of request IDs and channels to manage the flow of messages:
- For requests with a request or order ID:
- The Client generates a unique ID for the request.
- The MessageBus creates a dedicated channel for responses based on the request ID.
- Responses related to this request are sent through these channels.
- For requests without a request or order ID (due to TWS API design):
- The MessageBus creates a shared channel for responses of that request type.
- Responses related to these requests are routed through these shared channels.
- Note: Since these responses are not tied to specific request IDs, distinguishing between responses from concurrent requests of the same type requires careful handling.
The recommended application design is a separate Client instance per thread to avoid message routing issues.
- Define the new API method
- The API exposed to the user is defined on the Client struct.
- Define the interface for the new API on the Client struct. The actual implementation of the API is delegated to modules grouped by accounts, contracts, market data, orders and news.
- Include a docstring describing the API that includes and example of the API usage. for example.
- Ensure message identifiers ar defined.
- Make sure the appropriate incoming message and outgoing message identifiers are defined.
- Message identifiers for incoming messages and outgoing messages can be found in the interactive brokers codebase.
- Update the message type to request ID map.
- When processing messages received from TWS, the request id needs to be determined. This is not the same for all messages.
- A map of message type to request id position is maintained and may need to be updated.
- Add an implementation for the API in the appropriate group.
- Add an implementation for the API in the appropriate group: accounts, contracts, market data, orders or news.
- The implementation will provide an encoder to convert the request to the TWS format
- Send the message using the
MessageBus
.- Messages with a request id are sent using send_generic_message.
- Messages without a request id are sent using message type methods. e.g. request_next_order_id
- Implement a decoder for the response.
- Implement a decoder for the response received from the
MessageBus
. - Responses contain a channel that can you used to read the results as they become available.
- For APIs that return a single result, they may simply decode and return the result.
- For a collection of results, return a Subscription that can be used to iterate over results.
- Add test cases.
- Add test cases for the new functionality.
- Run coverage analysis. Your addition should improve or maintain the current coverage.
- Use
cargo tarpaulin
to generate coverage reports.
- Add an example.
- Add an example showing the API usage to the examples folder.
- Ensure your example is well-documented and can help users understand how to use the new API method.
The following environment variables are useful for troubleshooting:
RUST_LOG
- Changes the log level. Possible values aretrace
,debug
,info
,warn
,error
.IBAPI_RECORDING_DIR
- If this is set, the library logs messages between the library and TWS to the specified directory.
For example, the following sets the log level to debug
and instructs the library to log messages between it and TWS to /tmp/tws-messages
:
RUST_LOG=debug IBAPI_RECORDING_DIR=/tmp/tws-messages cargo run --bin find_contract_details
- Ensure build is clean and tests are passing.
cargo build --all-targets
cargo test
- Update version number.
- Update version number in Cargo.toml using semantic versioning.
- Commit and push your changes.
- Create tag with new version number.
git tag vX.Y.Z
git push origin vX.Y.Z
- Create a release.
- Create release pointing to new tag.
- Describe changes in release.
- Publish to crates.io.
- Before publishing, run a dry run to catch any issues:
cargo publish --dry-run
- If everything looks good, publish the crate:
cargo publish