| Crates.io | rtpx |
| lib.rs | rtpx |
| version | 1.0.5 |
| created_at | 2024-12-02 18:27:41.090359+00 |
| updated_at | 2025-03-28 20:23:54.613637+00 |
| description | Safe Rust bindings for CTP (Comprehensive Transaction Platform) and its variations for Chinese financial markets |
| homepage | https://github.com/glacierx/RTP |
| repository | https://github.com/glacierx/RTP |
| max_upload_size | |
| id | 1469098 |
| size | 23,047,049 |
Safe Rust bindings for CTP 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.
| 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 |
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));
}
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"] }
Feature flags allow you to choose which implementation to use:
ctp - Standard CTP implementation (default)atp - ATP implementationxtp - XTP implementationOnly one variant can be enabled at a time.
This package supports multiple versions of CTP and ATP SDKs. Here's how to use different versions:
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
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
# 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
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
Before running the examples, you'll need to modify the connection parameters in the source code:
examples/basic_usage.rs)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
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.
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
When writing your own tests, be aware that the import structure uses:
use rtp::trader::{GenericTraderApi, TraderApi, TraderSpi, ResumeType};
use rtp::trader::{DisconnectionReason, RspResult};
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:
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)
);
}
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.
Licensed under either of
at your option.
Note: This is an unofficial Rust binding. CTP is a trademark of Shanghai Futures Exchange.