ctp-rust 1.0.1

Safe Rust bindings for CTP (Comprehensive Transaction Platform) and its variations for Chinese financial markets
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
# CTP Rust SDK

一个为CTP (综合交易平台) 提供的安全、现代化的Rust绑定库,支持Linux和macOS系统。

## ✨ 特性

- 🔒 **类型安全**: 使用Rust的类型系统确保内存安全和线程安全
- 🌍 **跨平台支持**: 原生支持Linux和macOS (x86_64/ARM64)
- 📝 **编码自动转换**: 自动处理GB18030到UTF-8的编码转换
-**高性能**: 零拷贝设计,最小化性能开销
- 🛡️ **安全FFI**: 安全的C++库绑定,避免内存泄露和悬空指针
- 🐛 **调试支持**: 内置Debug日志功能,可配置日志输出

## 🚀 快速开始

### 项目结构

直接克隆并使用本项目:

```bash
git clone <repository-url>
cd ctp-rust
```

### 基本使用示例
整体架构流程

Rust Application
       ↓ 调用API
Rust FFI (ffi.rs)
       ↓ 调用C函数
C++ Wrapper (ctp_wrapper.cpp)
       ↓ 调用C++类方法
CTP C++ API (libthostmduserapi_se.dylib)
       ↓ 回调事件
C++ Bridge (spi_bridge.cpp)
       ↓ 转发回调
Rust Callback Functions
       ↓ 处理业务逻辑
Rust Application

#### 行情订阅

```rust
use ctp_rust::*;
use ctp_rust::api::{MdApi, CtpApi};
use ctp_rust::api::md_api::{MdSpiHandler, DepthMarketDataField};
use ctp_rust::types::{ReqUserLoginField, RspUserLoginField, RspInfoField};

// 实现行情回调处理器
struct MyMdHandler;

impl MdSpiHandler for MyMdHandler {
    fn on_front_connected(&mut self) {
        println!("行情前置已连接");
    }
    
    fn on_rsp_user_login(
        &mut self,
        user_login: Option<RspUserLoginField>,
        rsp_info: Option<RspInfoField>,
        request_id: i32,
        is_last: bool,
    ) {
        if let Some(rsp) = rsp_info {
            if rsp.is_success() {
                println!("登录成功");
            } else {
                if let Ok(msg) = rsp.get_error_msg() {
                    println!("登录失败: {}", msg);
                }
            }
        }
    }
    
    fn on_rtn_depth_market_data(&mut self, market_data: DepthMarketDataField) {
        println!("收到行情数据,最新价: {}", market_data.last_price);
    }
}

#[tokio::main]
async fn main() -> CtpResult<()> {
    // 创建行情API
    let mut md_api = MdApi::new(Some("./flow"), false, false)?;
    
    // 注册回调处理器
    md_api.register_spi(MyMdHandler)?;
    
    // 注册前置机地址
    md_api.register_front("tcp://180.168.146.187:10131")?;
    
    // 初始化
    md_api.init()?;
    
    // 创建登录请求
    let login_req = ReqUserLoginField::new("9999", "投资者账号", "密码")?
        .with_product_info("MyApp")?;
    
    // 发送登录请求
    md_api.req_user_login(&login_req)?;
    
    // 订阅行情
    md_api.subscribe_market_data(&["rb2501", "i2501"])?;
    
    // 等待API退出
    md_api.join()?;
    
    Ok(())
}
```

#### 交易接口(同步)

```rust
use ctp_rust::api::{TraderApi, CtpApi};
use ctp_rust::api::trader_api::{TraderSpiHandler, ReqAuthenticateField};

struct MyTraderHandler;

impl TraderSpiHandler for MyTraderHandler {
    fn on_front_connected(&mut self) {
        println!("交易前置已连接");
    }
    
    fn on_rsp_authenticate(
        &mut self,
        rsp_authenticate: Option<ctp_rust::api::trader_api::RspAuthenticateField>,
        rsp_info: Option<RspInfoField>,
        request_id: i32,
        is_last: bool,
    ) {
        if let Some(rsp) = rsp_info {
            if rsp.is_success() {
                println!("认证成功");
            }
        }
    }
}

#[tokio::main]
async fn main() -> CtpResult<()> {
    // 创建交易API
    let mut trader_api = TraderApi::new(Some("./flow"))?;
    
    // 注册回调处理器
    trader_api.register_spi(MyTraderHandler)?;
    
    // 注册前置机地址
    trader_api.register_front("tcp://180.168.146.187:10130")?;
    
    // 初始化
    trader_api.init()?;
    
    // 客户端认证
    let auth_req = ReqAuthenticateField {
        broker_id: [0; 11], // 填入实际的经纪公司代码
        user_id: [0; 16],   // 填入实际的用户代码
        // ... 其他字段
        ..Default::default()
    };
    
    trader_api.req_authenticate(&auth_req)?;
    
    Ok(())
}
```

#### 异步交易接口

```rust
use ctp_rust::api::AsyncTraderApi;
use ctp_rust::api::async_trader_api::AsyncTraderEvent;
use ctp_rust::types::{QryTradingAccountField, ReqUserLoginField};

#[tokio::main]
async fn main() -> CtpResult<()> {
    // 创建异步交易API
    let async_trader = AsyncTraderApi::new(Some("./flow"), Some(true)).await?;
    
    // 注册前置机并初始化
    async_trader.register_front("tcp://180.168.146.187:10130").await?;
    async_trader.init().await?;
    
    // 等待连接
    async_trader.wait_connected(30).await?;
    
    // 异步登录
    let login_req = ReqUserLoginField::new("9999", "投资者账号", "密码")?;
    let login_info = async_trader.login(&login_req, 30).await?;
    println!("登录成功: {:?}", login_info);
    
    // 异步查询资金账户
    let account_query = QryTradingAccountField::new("9999", "投资者账号")?;
    let accounts = async_trader.qry_trading_account(&account_query, 10).await?;
    
    for account in accounts {
        println!("可用资金: {:.2}", account.available);
        println!("当前余额: {:.2}", account.balance);
    }
    
    // 监听事件
    while let Some(event) = async_trader.recv_event().await {
        match event {
            AsyncTraderEvent::OrderReturn(order) => {
                println!("收到报单回报: {:?}", order);
            }
            AsyncTraderEvent::TradeReturn(trade) => {
                println!("收到成交回报: {:?}", trade);
            }
            _ => {}
        }
    }
    
    Ok(())
}
```

## 📖 详细文档

### 系统要求

- **操作系统**: Linux (x86_64) 或 macOS (x86_64/ARM64)
- **Rust版本**: 1.70+
- **CTP库**: 需要相应平台的CTP动态库

### 目录结构

```
ctp-rust/
├── src/
│   ├── lib.rs              # 主库入口
│   ├── error.rs            # 错误定义
│   ├── encoding.rs         # 编码转换
│   ├── types.rs            # 数据类型定义
│   ├── ffi.rs              # FFI绑定声明
│   └── api/
│       ├── mod.rs          # API模块
│       ├── md_api.rs       # 行情API
│       └── trader_api.rs   # 交易API
├── libs/ctp/
│   ├── common/
│   │   ├── debug_logger.h  # 调试日志头文件
│   │   └── debug_logger.cpp # 调试日志实现
│   ├── linux/
│   │   ├── include/        # Linux CTP头文件
│   │   ├── lib/            # Linux动态库
│   │   └── wrapper/        # Linux C++包装器
│   └── mac64/
│       ├── include/        # macOS CTP头文件
│       ├── thostmduserapi_se.framework/ # macOS框架
│       ├── thosttraderapi_se.framework/
│       └── wrapper/        # macOS C++包装器
├── examples/               # 示例代码
└── build.rs                # 构建脚本
```

### 编码处理

CTP库使用GB18030编码,而Rust默认使用UTF-8。本SDK自动处理两种编码之间的转换:

```rust
use ctp_rust::encoding::GbkConverter;

// UTF-8 转 GB18030
let gb_bytes = GbkConverter::utf8_to_gb18030("期货合约")?;

// GB18030 转 UTF-8
let utf8_string = GbkConverter::gb18030_to_utf8(&gb_bytes)?;

// 固定长度字节数组转换
use ctp_rust::types::{InstrumentIdType, StringConvert};

let instrument_id = InstrumentIdType::from_utf8_string("rb2501")?;
let back_to_string = instrument_id.to_utf8_string()?;
```

### 错误处理

SDK提供了完整的错误处理机制:

```rust
use ctp_rust::error::{CtpError, CtpResult};

match some_ctp_function() {
    Ok(result) => println!("操作成功: {:?}", result),
    Err(CtpError::ConnectionError(msg)) => println!("连接错误: {}", msg),
    Err(CtpError::AuthenticationError(msg)) => println!("认证错误: {}", msg),
    Err(CtpError::BusinessError(code, msg)) => {
        println!("业务错误 [{}]: {}", code, msg);
    }
    Err(e) => println!("其他错误: {}", e),
}
```

### 平台支持

#### Linux

```bash
# 确保系统有必要的库
sudo apt-get install build-essential

# 设置库文件路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./libs/ctp/linux/lib

# 运行程序
cargo run
```

#### macOS

```bash
# 设置库文件路径
export DYLD_FRAMEWORK_PATH=$DYLD_FRAMEWORK_PATH:./libs/ctp/mac64
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:./libs/ctp/mac64/wrapper

# 在Apple Silicon Mac上可能需要Rosetta
# 如果遇到架构问题,可以用Rosetta运行:
arch -x86_64 cargo run
```

## 🔧 构建配置

### 构建和调试日志

项目内置了调试日志功能,可以帮助排查问题:

```rust
use ctp_rust::ffi::{CTP_InitializeDebugLogging, CtpLogConfig};
use std::ffi::CString;

// 启用控制台日志输出
let log_path = CString::new("").unwrap();
let config = CtpLogConfig {
    enable_debug: 1,
    log_file_path: std::ptr::null(), // 使用null输出到控制台
    max_file_size_mb: 10,
    max_backup_files: 5,
};

unsafe {
    CTP_InitializeDebugLogging(&config);
}

// 或者输出到文件
let log_path = CString::new("./ctp_debug.log").unwrap();
let config = CtpLogConfig {
    enable_debug: 1,
    log_file_path: log_path.as_ptr(),
    max_file_size_mb: 10,
    max_backup_files: 5,
};
```

### 编译和运行

```bash
# 构建项目(会自动编译C++包装器)
cargo build

# 运行示例
cargo run --example trader_basic
```

### 自定义构建

如果你需要自定义CTP库的位置,可以设置环境变量:

```bash
export CTP_LIB_PATH=/path/to/your/ctp/libs
export CTP_INCLUDE_PATH=/path/to/your/ctp/headers
```

### 功能特性

项目使用条件编译,根据可用的CTP库自动启用相应功能:
- `md_api`: 当找到行情API库时自动启用
- `trader_api`: 当找到交易API库时自动启用
- `test_mode`: 当没有CTP库时启用测试模式

## 📋 API参考

### 主要类型

- `MdApi`: 同步行情API接口
- `AsyncMdApi`: 异步行情API接口
- `TraderApi`: 同步交易API接口
- `AsyncTraderApi`: 异步交易API接口
- `ReqUserLoginField`: 用户登录请求
- `RspUserLoginField`: 用户登录响应
- `DepthMarketDataField`: 深度行情数据
- `OrderField`: 报单信息
- `TradeField`: 成交信息

### 回调接口

- `MdSpiHandler`: 行情回调处理接口(同步)
- `TraderSpiHandler`: 交易回调处理接口(同步)
- `AsyncMdEvent`: 异步行情事件
- `AsyncTraderEvent`: 异步交易事件

### 编码工具

- `GbkConverter`: GB18030/UTF-8编码转换器
- `StringConvert`: 字符串转换特质

## 🧪 测试

运行所有测试:

```bash
cargo test
```

运行编码测试:

```bash
cargo test --test encoding_tests
```

运行集成测试(需要CTP库):

```bash
cargo test --features integration
```

## 📚 示例

更多示例请查看 `examples/` 目录:

- `md_basic.rs`: 基础行情订阅(同步)
- `async_md_basic.rs`: 基础行情订阅(异步)
- `trader_basic.rs`: 基础交易功能,包含资金账户和持仓查询(同步)
- `async_trader_basic.rs`: 基础交易功能(异步)
- `encoding_demo.rs`: 编码转换示例
- `error_handling.rs`: 错误处理示例
- `debug_logger.rs`: 调试日志功能示例

### 运行示例

```bash
# 设置环境变量(以实际配置为准)
export CTP_BROKER_ID="9999"
export CTP_INVESTOR_ID="your_investor_id"
export CTP_PASSWORD="your_password"
export CTP_MD_FRONT="tcp://180.168.146.187:10131"
export CTP_TRADER_FRONT="tcp://180.168.146.187:10130"
export CTP_FLOW_PATH="./ctp_flow"

# 运行交易示例(macOS)
DYLD_FRAMEWORK_PATH=libs/ctp/mac64 DYLD_LIBRARY_PATH=libs/ctp/mac64/wrapper cargo run --example trader_basic

# 运行交易示例(Linux)
LD_LIBRARY_PATH=libs/ctp/linux/lib:libs/ctp/linux/wrapper cargo run --example trader_basic
```

## 🛠️ 开发指南

### 项目架构

```
Rust应用程序
    ↓ 调用API
Rust FFI层 (ffi.rs)
    ↓ 调用C函数
C++ Wrapper层 (ctp_wrapper.cpp)
    ↓ 调用C++方法
CTP C++ API (Framework/动态库)
    ↓ SPI回调
C++ Bridge层 (spi_bridge.cpp)
    ↓ 转发回调
Rust回调函数
    ↓ 业务逻辑处理
Rust应用程序
```

架构特点:
- **跨平台兼容**: Linux使用.so动态库,macOS使用.framework
- **调试日志**: 内置debug_logger提供详细的调用跟踪
- **内存安全**: 使用RAII和智能指针管理资源

### 添加新的 API 方法

1. **更新 C++ wrapper**
   ```cpp
   // 在 ctp_wrapper.h 中添加函数声明
   int CThostFtdcTraderApi_ReqNewFunction(void* api, void* req, int request_id);
   
   // 在 ctp_wrapper.cpp 中添加实现
   int CThostFtdcTraderApi_ReqNewFunction(void* api, void* req, int request_id) {
       if (api) {
           return static_cast<CThostFtdcTraderApi*>(api)->ReqNewFunction(
               static_cast<RequestStruct*>(req), request_id);
       }
       return -1;
   }
   ```

2. **更新 Rust FFI 声明**
   ```rust
   // 在 src/ffi.rs 中添加
   extern "C" {
       pub fn CThostFtdcTraderApi_ReqNewFunction(
           api: *mut c_void,
           req: *const c_void,
           request_id: c_int,
       ) -> c_int;
   }
   ```

3. **更新 Rust API**
   ```rust
   // 在 src/api/trader_api.rs 中添加
   pub fn req_new_function(&mut self, req: &RequestStruct) -> CtpResult<i32> {
       // 实现逻辑
   }
   ```

4. **重新编译项目**
   ```bash
   cargo build
   ```

### 添加新的回调

1. **更新 SPI Bridge**
   ```cpp
   // 在 spi_bridge.h 中添加回调类型
   typedef void (*OnNewCallbackFunction)(void* user_data, void* data, int param);
   
   // 在 TraderSpiCallbacks 结构中添加
   OnNewCallbackFunction on_new_callback;
   
   // 在 spi_bridge.cpp 中实现
   virtual void OnNewCallback(DataStruct* data, int param) override {
       if (callbacks.on_new_callback) {
           callbacks.on_new_callback(callbacks.user_data, data, param);
       }
   }
   ```

2. **更新 Rust 回调处理**
   ```rust
   // 在 TraderSpiHandler trait 中添加
   fn on_new_callback(&mut self, data: DataStruct, param: i32) {
       // 默认实现
   }
   
   // 实现回调函数
   extern "C" fn on_new_callback_impl(
       user_data: *mut c_void,
       data: *mut c_void,
       param: c_int,
   ) {
       // 回调实现
   }
   ```

### 调试技巧

1. **启用调试日志**
   ```rust
   env_logger::init();
   log::debug!("调试信息");
   ```

2. **使用 gdb/lldb 调试 C++ 部分**
   ```bash
   # macOS
   lldb target/debug/examples/trader_basic
   
   # Linux
   gdb target/debug/examples/trader_basic
   ```

3. **内存安全检查**
   ```bash
   cargo valgrind run --example trader_basic
   ```

## 🤝 贡献

欢迎贡献代码!请遵循以下步骤:

1. Fork本仓库
2. 创建feature分支 (`git checkout -b feature/amazing-feature`)
3. 提交你的修改 (`git commit -m 'Add some amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 开启Pull Request

## ⚠️ 注意事项

1. **库文件**: 需要获取相应平台的CTP库文件并放置在正确位置
2. **网络环境**: 连接CTP服务器需要稳定的网络环境
3. **账户权限**: 需要有效的CTP账户和相应的交易权限
4. **风险提示**: 期货交易有风险,请谨慎使用

## 📄 许可证

本项目采用MIT或Apache-2.0双重许可证。详见 [LICENSE-MIT](LICENSE-MIT) 和 [LICENSE-APACHE](LICENSE-APACHE) 文件。

## 🔗 相关链接

- [CTP官网]http://www.sfit.com.cn/
- [Rust官网]https://www.rust-lang.org/
- [CTP开发者社区]https://www.zhihu.com/topic/20015421

## 📞 联系方式

如有问题或建议,请通过以下方式联系:

- GitHub Issues: 通过项目仓库提交问题

---

**免责声明**: 本软件仅供学习和研究使用,作者不对因使用本软件导致的任何损失承担责任。期货投资有风险,入市需谨慎。