6 stable releases
new 1.0.5 | Mar 28, 2025 |
---|---|
1.0.4 | Mar 25, 2025 |
1.0.3 | Dec 18, 2024 |
1.0.2 | Dec 9, 2024 |
1.0.0 | Dec 2, 2024 |
#28 in Finance
83 downloads per month
22MB
35K
SLoC
Contains (ELF lib, 5.5MB) libs/ctp/linux64/thosttraderapi_se.so, (ELF lib, 4.5MB) libs/atp/linux64/libthostmduserapi.so, (ELF lib, 5MB) libs/atp/linux64/libthosttraderapi.so, (ELF lib, 5MB) libs/ctp/linux64/thostmduserapi_se.so
rtpx (RTP)
Safe Rust bindings for CTP and its variations
๐ฆ rtpx: Safe Rust Bindings for CTP Trading System and its variations
rtpx
provides safe and ergonomic Rust bindings for the CTP (Comprehensive Transaction Platform) trading system and its variants (ATP, XTP), widely used in Chinese financial markets. This project aims to bring Rust's safety and performance guarantees to the CTP ecosystem while maintaining compatibility with various CTP-compatible implementations.
Supported SDK versions
sdk | version | original URL |
---|---|---|
CTP | 6.7.7_210240607 | http://www.sfit.com.cn/DocumentDown/api_3/5_2_2/v6.7.7_traderapi_20240607.zip |
ATP | 6.3.15 | N/A |
Changelog
v1.0.5
- Fixed build issue when compiling with the ATP feature by resolving SO_NAME constant redefinition in build.rs
๐ Features
- Safe Abstractions: Zero-cost abstractions over CTP's C++ interfaces with Rust's safety guarantees
- Multiple CTP Variants: Support for CTP, ATP and XTP through feature flags
- Error Handling: Rust-native error handling replacing C++ exceptions
- Cross-Platform: Windows and Linux support
- Zero Overhead: Direct FFI bindings with no runtime cost
- Type Safety: Strong typing for market data and trading interfaces
๐ Basic Usage
use std::ffi::CString;
use std::thread;
use std::time::Duration;
// Import the RTP trader API with required features
use rtp::trader::{GenericTraderApi, TraderApi, TraderSpi, ResumeType};
use rtp::trader::{DisconnectionReason, RspResult};
// Create a simple TraderSpi implementation
struct MyTraderSpi {
connected: bool,
}
impl MyTraderSpi {
fn new() -> Self {
MyTraderSpi { connected: false }
}
}
impl TraderSpi for MyTraderSpi {
fn on_front_connected(&mut self) {
println!("Connected to trading server");
self.connected = true;
}
fn on_front_disconnected(&mut self, reason: DisconnectionReason) {
println!("Disconnected from trading server: {:?}", reason);
self.connected = false;
}
}
fn main() {
// Create a new instance of TraderApi
let flow_path = CString::new("./flow_path").unwrap();
let mut trader = TraderApi::new(flow_path);
// Register SPI for callbacks
let trader_spi = Box::new(MyTraderSpi::new());
trader.register_spi(trader_spi);
// Configure the trader API
trader.subscribe_public_topic(ResumeType::Quick);
trader.subscribe_private_topic(ResumeType::Quick);
// Register a trading server front
trader.register_front(CString::new("tcp://trading.server.address:port").unwrap());
// Initialize API (non-blocking call)
trader.init();
// Allow some time for connection and processing
thread::sleep(Duration::from_secs(5));
}
๐ฆ Installation
Add this to your Cargo.toml
:
[dependencies]
rtpx = "1.0.3"
By default, the CTP variant is enabled. To use ATP or XTP instead:
[dependencies]
rtpx = { version = "1.0.3", default-features = false, features = ["atp"] }
๐ง Supported CTP Variants
Feature flags allow you to choose which implementation to use:
ctp
- Standard CTP implementation (default)atp
- ATP implementationxtp
- XTP implementation
Only one variant can be enabled at a time.
๐ Using Different SDK Versions
This package supports multiple versions of CTP and ATP SDKs. Here's how to use different versions:
Using a Different CTP Version
-
Download your desired CTP version from the official website (http://www.sfit.com.cn/)
-
Place the SDK files in your project:
your_project/ โโโ sdk/ โ โโโ ctp/ โ โโโ include/ โ โ โโโ ThostFtdcMdApi.h โ โ โโโ ThostFtdcTraderApi.h โ โ โโโ ThostFtdcUserApiStruct.h โ โโโ lib/ โ โโโ libthostmduserapi_se.so # Linux โ โโโ libthosttraderapi_se.so # Linux
-
Update your project's build configuration:
[dependencies] rtpx = { version = "1.0.4", default-features = false, features = ["ctp"] } [package.metadata.rtpx] ctp_sdk_path = "sdk/ctp" # Path to your CTP SDK
Using a Different ATP Version
-
Obtain the ATP SDK files from your broker
-
Place the SDK files similarly:
your_project/ โโโ sdk/ โ โโโ atp/ โ โโโ include/ โ โ โโโ AtpTraderApi.h โ โ โโโ AtpUserApiStruct.h โ โโโ lib/ โ โโโ libatptraderapi.so # Linux โ โโโ libatpmduserapi.so # Linux
-
Update your project's build configuration:
[dependencies] rtpx = { version = "1.0.4", default-features = false, features = ["atp"] } [package.metadata.rtpx] atp_sdk_path = "sdk/atp" # Path to your ATP SDK
Important Notes
- Always ensure binary compatibility between your chosen SDK version and your broker's trading system
- Test thoroughly with your specific SDK version in a simulation environment before using in production
- Some features might vary between different SDK versions
- When upgrading SDK versions, review the changelog for breaking changes
- The package's default SDK versions are tested and known to work, but you can override them as shown above
๐ ๏ธ Building from Source
# Clone the repository
git clone https://github.com/glacierx/RTP
cd RTP
# Build with CTP (default)
cargo build --release
# Build with ATP
cargo build --release --no-default-features --features=atp
# Run tests
cargo test
๐ Running Examples
The repository includes examples demonstrating basic usage of the trading API. The most comprehensive example is basic_usage.rs
, which demonstrates connecting to a trading server, logging in, and querying account information and positions.
To run the examples:
# Run the basic usage example with CTP (default)
cargo run --example basic_usage
# Run the basic usage example with ATP
cargo run --example basic_usage --no-default-features --features=atp
# Run the basic usage example with XTP
cargo run --example basic_usage --no-default-features --features=xtp
Configuring the Examples
Before running the examples, you'll need to modify the connection parameters in the source code:
- Open the example file (e.g.,
examples/basic_usage.rs
) - Update the following values with your actual credentials:
let front_address = "tcp://180.168.146.187:10130"; // Change to your server let broker_id = "9999"; // Change to your broker ID let investor_id = "your_investor_id"; // Change to your actual ID let password = "your_password"; // Change to your actual password
Note on Flow Path Files
The examples create flow files in the current directory. These files are used by the CTP/ATP/XTP APIs to store session information. The default flow path is ./flow_path
, but you can change it if needed.
๐งช Testing
The library includes tests showing basic usage patterns for CTP and ATP. These are non-connecting tests that demonstrate API initialization and proper structure but don't connect to real servers.
To run the tests:
# Run CTP tests (default)
cargo test
# Run ATP tests
cargo test --no-default-features --features=atp
โ ๏ธ Note on Writing Tests
When writing your own tests, be aware that the import structure uses:
use rtp::trader::{GenericTraderApi, TraderApi, TraderSpi, ResumeType};
use rtp::trader::{DisconnectionReason, RspResult};
๐ Troubleshooting
Working with CTP Enum Values
CTP/ATP/XTP have many enum values that are defined in their C++ headers. In the Rust binding, these are often represented as primitive types (like u8
) with specific values. When working with these values, you may need to use the raw numeric values rather than trying to access enum variants.
For example, when dealing with position direction (TThostFtdcPosiDirectionType):
// Correct way - use direct numeric values:
let position_char = match position.PosiDirection {
2 => 'L', // Long position
3 => 'S', // Short position
1 => 'N', // Net position
_ => '?', // Unknown
};
Common CTP enum values:
- Position Direction (TThostFtdcPosiDirectionType): 1=Net, 2=Long, 3=Short
- Direction (TThostFtdcDirectionType): '0'=Buy, '1'=Sell
- Order Status (TThostFtdcOrderStatusType): '0'=AllTraded, '1'=PartTradedQueueing, '2'=PartTradedNotQueueing, '3'=NoTradeQueueing, '4'=NoTradeNotQueueing, '5'=Canceled, 'a'=Unknown, 'b'=NotTouched, 'c'=Touched
Setting String Values in CTP Structs
When setting string values in CTP structs, you need to handle the conversion from Rust strings to C-style character arrays:
// Example of setting BrokerID and UserID in a login field
unsafe {
use std::ptr::copy_nonoverlapping;
let broker_bytes = broker_id.as_bytes();
let user_bytes = user_id.as_bytes();
copy_nonoverlapping(
broker_bytes.as_ptr(),
req_user_login.BrokerID.as_mut_ptr() as *mut u8,
std::cmp::min(broker_bytes.len(), req_user_login.BrokerID.len() - 1)
);
copy_nonoverlapping(
user_bytes.as_ptr(),
req_user_login.UserID.as_mut_ptr() as *mut u8,
std::cmp::min(user_bytes.len(), req_user_login.UserID.len() - 1)
);
}
โ ๏ธ Disclaimer
This software is provided "as is", without warranty of any kind. Trading in financial markets carries significant risk. Make sure to test thoroughly in a simulated environment before using in production.
๐ License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
๐ Acknowledgments
- CTP development team for the original C++ SDK
- Rust FFI community for guidance and tools
- Contributors who helped make this project possible
- Author of the project ctp-rs. (This project is the cornerstone of CTP migrations in the world of RustLang helped a lot of people. It is archived and read only, hopefully the author is rich enough to retire)
Note: This is an unofficial Rust binding. CTP is a trademark of Shanghai Futures Exchange.
Dependencies
~5โ13MB
~135K SLoC