### Run Examples Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Instructions on how to run the provided examples for Ctp2rs. Examples cover various use cases like market data retrieval, local CTP simulation, and cross-version dynamic loading. ```sh cargo run --example ``` -------------------------------- ### Run the Insecure POC Example Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/insecure/README.md Execute the demonstration using environment variables for SimNow credentials. ```shell > cd examples/insecure/ > SIMNOW_USER_ID={your_simnow_account_id} SIMNOW_PASS={your_simow_account_password} cargo run ``` -------------------------------- ### Run LocalCTP Query Example Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/localctp/README.md Navigate to the example directory and run the query binary using Cargo. This command compiles and executes the ctp_query example. ```sh > cd examples/localctp/ > cargo run -p localctp --bin query ``` -------------------------------- ### Run Channel Sample Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/channel/README.md Navigate to the channel example directory and execute the command. Ensure you set your SIMNOW_USER_ID and RUST_LOG environment variables. ```shell > cd examples/channel/ > SIMNOW_USER_ID={your_simnow_account_id} RUST_LOG=debug cargo run ``` -------------------------------- ### POC Execution Output Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/insecure/README.md Example log output showing successful API initialization and login. ```log tdapi start here! base_dir: get_api_version: v6.7.2_20230913 10:48:10.4926 tdapi init tdspi.on_front_connected !!! on_rsp_authenticate ErrorID[0] Message[正确] req_user_login result: 0 ErrorID[0] Message[正确] ``` -------------------------------- ### Run TTS-SOPT Sample Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/tts_sopt/README.md Navigate to the example directory and execute the sample using Cargo, providing your OpenCTP credentials as environment variables. ```sh > cd examples/tts_sopt/ > OPENCTP_USER_ID='your_openctp_account_id' OPENCTP_PASS='your_openctp_accout_password' cargo run ``` -------------------------------- ### Run OpenCTP Simulation Environment Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/openctp/README.md Execute the OpenCTP example in simulation mode. Ensure you replace 'your_openctp_account_id' and 'your_openctp_accout_password' with your actual credentials. ```bash > cd examples/openctp/ > cargo run -- --environment sim --user-id 'your_openctp_account_id' --password 'your_openctp_accout_password' ``` -------------------------------- ### Run OpenCTP TTS Environment Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/openctp/README.md Execute the OpenCTP example in TTS mode, connecting to both market data and trading counters. Replace placeholders with your credentials. ```bash > cd examples/openctp/ > cargo run -- --environment tts --user-id 'your_openctp_account_id' --password 'your_openctp_accout_password' ``` -------------------------------- ### Place Order Example - req_order_insert Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Demonstrates how to insert a limit order with specific contract details, direction, and volume. Ensure correct `BrokerID`, `InvestorID`, and `InstrumentID` are used. ```rust use ctp2rs::ffi::AssignFromString; use ctp2rs::v1alpha1::*; fn send_order(tdapi: &TraderApi, request_id: i32) { let mut order = CThostFtdcInputOrderField::default(); // 基本字段 order.BrokerID.assign_from_str("9999"); order.InvestorID.assign_from_str("你的用户名"); order.InstrumentID.assign_from_str("ag2512"); // 合约代码 order.ExchangeID.assign_from_str("SHFE"); // 交易所 // 下单方向和开平 order.Direction = THOST_FTDC_D_Buy; // 买入 order.CombOffsetFlag[0] = THOST_FTDC_OF_Open as i8; // 开仓 order.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation as i8; // 投机 // 价格和数量 order.LimitPrice = 6500.0; // 限价 order.VolumeTotalOriginal = 1; // 数量 // 订单类型 order.OrderPriceType = THOST_FTDC_OPT_LimitPrice; // 限价单 order.TimeCondition = THOST_FTDC_TC_GFD; // 当日有效 order.VolumeCondition = THOST_FTDC_VC_AV; // 任意数量 order.ContingentCondition = THOST_FTDC_CC_Immediately; // 立即触发 order.MinVolume = 1; let ret = tdapi.req_order_insert(&mut order, request_id); println!("下单请求返回: {}", ret); // 0 表示成功发送 } ``` -------------------------------- ### Displaying clang Version Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Shows the installed clang compiler version. This is useful for verifying the C++ toolchain compatibility. ```shell clang --version ``` -------------------------------- ### Basic CTP API Initialization Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Example of initializing the MdApi with a dynamic library path, which varies based on the target operating system. Ensure the path points to the correct CTP API dynamic library. ```rust #[cfg(target_os = "macos")] let dynlib_path = "../../ctp-dyn/api/ctp/v6.7.2/v6.7.2_20231016/thostmduserapi_se.framework/thostmduserapi_se"; #[cfg(target_os = "linux")] let dynlib_path = "../../ctp-dyn/api/ctp/v6.7.2/v6.7.2_20230913_api_traderapi_se_linux64/thostmduserapi_se.so"; #[cfg(target_os = "windows")] let dynlib_path = "../../ctp-dyn/api/ctp/v6.7.2/v6.7.2_20230913_api_traderapi64_se_windows/thostmduserapi_se.dll" let mdapi = MdApi::create_api(dynlib_path, "./md_", false, false); ... ``` -------------------------------- ### Cancel Order Example - req_order_action Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Shows how to cancel an existing order using its `OrderRef`, `FrontID`, and `SessionID`. The `ActionFlag` must be set to `THOST_FTDC_AF_Delete`. ```rust use ctp2rs::ffi::AssignFromString; use ctp2rs::v1alpha1::*; fn cancel_order( tdapi: &TraderApi, request_id: i32, order_ref: &str, front_id: i32, session_id: i32, ) { let mut action = CThostFtdcInputOrderActionField::default(); action.BrokerID.assign_from_str("9999"); action.InvestorID.assign_from_str("你的用户名"); action.InstrumentID.assign_from_str("ag2512"); action.ExchangeID.assign_from_str("SHFE"); // 通过 OrderRef + FrontID + SessionID 定位订单 action.OrderRef.assign_from_str(order_ref); action.FrontID = front_id; action.SessionID = session_id; action.ActionFlag = THOST_FTDC_AF_Delete; // 删除订单 let ret = tdapi.req_order_action(&mut action, request_id); println!("撤单请求返回: {}", ret); } ``` -------------------------------- ### OpenCTP Simulation Environment Output Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/openctp/README.md Sample output from running the OpenCTP example in simulation mode, showing API version, connection status, and market data. ```log Running with environment: Sim mdapi start here! md dynlib_path: ./git/pseudo/ctp2rs/examples/openctp/../../../ctp-dyn/api/ctp/v6.7.2/v6.7.2_MacOS_20231016/thostmduserapi_se.framework/thostmduserapi_se tdapi start here! td dynlib_path: ./git/pseudo/ctp2rs/examples/openctp/tts/v6_7_2/mac_arm64/thosttraderapi_se.dylib md get_api_version: v6.7.2_MacOS_20231016 15:00:00 mdapi init md loop td get_api_version: V6_7_2 tdapi init td loop tdspi.on_front_connected !!! on_rsp_authenticate ErrorID[0] Message[] req_user_login result: 0 ErrorID[0] Message[成功] req_user_login result: 0 ErrorID[0] Message[] mdspi.on_front_connected ErrorID[0] Message[CTP:No Error] on_rsp_user_login! ErrorID[0] Message[CTP:No Error] on_rsp_sub_market_data: instrument_id["ag2510"], 0, false ErrorID[0] Message[CTP:No Error] on_rsp_sub_market_data: instrument_id["au2510"], 0, true OnRtnDepthMarketData! [20250714 11:29:57 0] ag2510 last_price: 9198 OnRtnDepthMarketData! [20250714 11:29:57 0] au2510 last_price: 778.3000000000001 req_qry_investor_position result: 0 ErrorID[0] Message[成功] position hold None ``` -------------------------------- ### Displaying rustc Version Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Shows the installed Rust compiler version. This is essential for ensuring the correct Rust toolchain is active. ```shell rustc --version ``` -------------------------------- ### LocalCTP Query Output Log Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/localctp/README.md This log shows the output from running the LocalCTP query example. It includes initialization messages, connection status, subscription details, and trade/order return information. ```log [LocalCTP] Load local config file, running_mode:0(REALTIME_MODE), backtest_startdate:20250228, exit_after_settlement:0, settlement_time:17:00:00 OpenSqlDB done!~ [2025-09-26T14:19:13Z INFO query] Start query binary! Message queue initialized at path: LocalCTP version: LocalCTP V1.0.0 By QiuShui(Aura) QQ1005018695 [2025-09-26T14:19:13Z DEBUG localctp::localctpx] register name_server "" [2025-09-26T14:19:13Z INFO localctp::localctpx] register front tcp://182.254.243.31:30001 [2025-09-26T14:19:13Z DEBUG localctp::localctpx] register done [2025-09-26T14:19:13Z DEBUG localctp::localctpx] subscribe topic done [2025-09-26T14:19:13Z DEBUG localctp::localctpx] init done MdReceiver thread started [2025-09-26T14:19:13Z INFO localctp::localctpx] 前端连接成功回报 OnFrontConnected [2025-09-26T14:19:13Z INFO localctp::localctpx] call req_authenticate done [2025-09-26T14:19:13Z INFO localctp::localctpx] 认证成功回报 OnRspAuthenticate [LocalCTP] tradingDay is empty, let's init it! [2025-09-26T14:19:13Z INFO localctp::localctpx] 完成认证 [2025-09-26T14:19:13Z INFO localctp::localctpx] 开始输入行情 [2025-09-26T14:19:13Z DEBUG localctp::localctpx] ag2506 -> 894.05 [2025-09-26T14:19:13Z DEBUG localctp::localctpx] ag2506 -> 2853.48 No message received in timeout period [2025-09-26T14:19:14Z DEBUG localctp::localctpx] insert_limit_order: ag2506 -> 50000 [2025-09-26T14:19:14Z DEBUG localctp::localctpx] ag2506 -> 398.69 [2025-09-26T14:19:14Z DEBUG localctp::localctpx] Order successfully inserted. [2025-09-26T14:19:14Z DEBUG localctp::localctpx] ag2506 -> 3061.96 No message received in timeout period [2025-09-26T14:19:15Z DEBUG localctp::localctpx] ag2506 -> 3389.04 [2025-09-26T14:19:15Z DEBUG localctp::localctpx] ag2506 -> 100.67 [LocalCTP] tradingDay is 20250929 [LocalCTP] next Settlement Time is 2025-09-29 17:00:00 [2025-09-26T14:19:16Z DEBUG localctp::localctpx] ag2506 -> 2584.06 No message received in timeout period [2025-09-26T14:19:16Z INFO localctp::localctpx] 其它回报 [2025-09-26T14:19:16Z INFO localctp::localctpx] 报单成功回报 Order Return: BrokerID: 9999, InvestorID: 111111, ExchangeID: SHFE, OrderRef: 123, OrderStatus: 未知状态, InstrumentID: ag2506 [2025-09-26T14:19:16Z INFO localctp::localctpx] 报单成功回报 Order Return: BrokerID: 9999, InvestorID: 111111, ExchangeID: SHFE, OrderRef: 123, OrderStatus: 未成交还在队列中, InstrumentID: ag2506 [2025-09-26T14:19:16Z INFO localctp::localctpx] 成交回报 OnRtnTrade: OrderRef: 123, BrokerID: 9999, InvestorID: 111111, ExchangeID: SHFE, TradeID: 1758896353996, InstrumentID: ag2506, Price: 1774.65, Volume: 1 No message received in timeout period Quit the CSqliteHandler, let's sync for the last time...! ``` -------------------------------- ### Displaying g++ Version Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Shows the installed g++ compiler version. This is relevant for projects that rely on the GNU C++ toolchain. ```shell g++ --version ``` -------------------------------- ### OpenCTP TTS Environment Output Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/openctp/README.md Sample output from running the OpenCTP example in TTS mode, detailing API versions, connection events, and market data reception. ```log Running with environment: Tts mdapi start here! md dynlib_path: ./git/pseudo/ctp2rs/examples/openctp/tts/v6_7_2/mac_arm64/thostmduserapi_se.dylib tdapi start here! td dynlib_path: ./git/pseudo/ctp2rs/examples/openctp/tts/v6_7_2/mac_arm64/thosttraderapi_se.dylib md get_api_version: V6_6_9 td get_api_version: V6_7_2 mdapi init md loop tdapi init td loop mdspi.on_front_connected tdspi.on_front_connected !!! on_rsp_authenticate ErrorID[0] Message[] req_user_login result: 0 ErrorID[0] Message[成功] on_rsp_user_login! ErrorID[0] Message[] on_rsp_sub_market_data: instrument_id["ag2510"], 0, true OnRtnDepthMarketData! [20250714 10:36:32 0] ag2510 last_price: 9216 ErrorID[0] Message[] on_rsp_sub_market_data: instrument_id["au2510"], 0, true OnRtnDepthMarketData! [20250714 10:36:32 0] au2510 last_price: 778.1200000000001 ErrorID[0] Message[成功] req_user_login result: 0 ErrorID[0] Message[] OnRtnDepthMarketData! [20250714 10:36:32 0] ag2510 last_price: 9216 OnRtnDepthMarketData! [20250714 10:36:32 0] au2510 last_price: 778.1 OnRtnDepthMarketData! [20250714 10:36:33 0] ag2510 last_price: 9216 OnRtnDepthMarketData! [20250714 10:36:33 0] au2510 last_price: 778.1200000000001 req_qry_investor_position result: 0 ErrorID[0] Message[成功] position hold None on_rsp_qry_investor_position finish! OnRtnDepthMarketData! [20250714 10:36:33 0] ag2510 last_price: 9215 OnRtnDepthMarketData! [20250714 10:36:33 0] au2510 last_price: 778.1 OnRtnDepthMarketData! [20250714 10:36:34 0] ag2510 last_price: 9215 OnRtnDepthMarketData! [20250714 10:36:34 0] au2510 last_price: 778.1400000000001 OnRtnDepthMarketData! [20250714 10:36:34 0] ag2510 last_price: 9216 ``` -------------------------------- ### Get API Version - get_api_version Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Retrieves the CTP API version from a dynamic library. Supports automatic detection of market data or trading interfaces. Ensure the library path is correct. ```rust use ctp2rs::v1alpha1::get_api_version; // 自动探测动态库类型并获取版本 match get_api_version("./thostmduserapi_se.so") { Ok(version) => println!("API Version: {}", version), Err(e) => eprintln!("加载失败: {:?}", e), } // 输出: API Version: v6.7.2_20230913 10:32:39.567 ``` -------------------------------- ### Create MdApi instance with create_api Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Instantiate the market data API by providing the path to the dynamic library and configuration parameters. ```rust use ctp2rs::v1alpha1::MdApi; // Linux 平台 #[cfg(target_os = "linux")] let dynlib_path = "./ctp-dyn/api/ctp/v6.7.2/v6.7.2_20230913_api_traderapi_se_linux64/thostmduserapi_se.so"; // macOS 平台 #[cfg(target_os = "macos")] let dynlib_path = "./ctp-dyn/api/ctp/v6.7.2/v6.7.2_MacOS_20231016/thostmduserapi_se.framework/thostmduserapi_se"; // Windows 平台 #[cfg(target_os = "windows")] let dynlib_path = "./ctp-dyn/api/ctp/v6.7.2/v6.7.2_20230913_api_traderapi64_se_windows/thostmduserapi_se.dll"; // 创建行情 API 实例 // 参数: 动态库路径, 流文件目录, 是否使用UDP, 是否使用组播 let mdapi = MdApi::create_api(dynlib_path, "./md_flow/", false, false); // 获取 API 版本号 println!("API Version: {}", mdapi.get_api_version()); // 输出: API Version: v6.7.2_20230913 10:32:39.567 ``` -------------------------------- ### TTS-SOPT Sample Output Log Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/tts_sopt/README.md This log shows the initialization process, API version retrieval, connection status, and market data updates for the TTS-SOPT sample in the OpenCTP environment. ```log tdapi start here! mdapi start here! base dir:D:lproject\ctp2rs\examples\sopt md dynlib path: D: \project\ctp2rs\examples\sopt\./tts/v3.7.3/20248918_traderapi64_windows_se/soptthostmduserapi_se.dll base dir:D:projectictp2rslexamples\sopt td dynlib path: D: \project\ctp2rs\examples\sopt\./tts/v3.7.3/20248918_traderapi64_windows_se/soptthosttraderapi_se.dll get api version: openctp-ttsopt v3_7_0 get api version: openctp-ttsopt v3.7.8 mdapi init md looptdapi init td loop mdspi.on_front_connected tdspi.on_front_connected !!! on_rsp_authenticate ErrorID[0] Message[] req_user_login result: 0 ErrorID[0] Message[成功] on_rsp_user_login! ErrorID[0] Message[] on_rsp_sub_market_data: instrument_id["18888261"],0,true ErrorID[0] Message[] reg_user_login_result: 0 ErrorID[0] Message[成功] OnRtnDepthMarketData. 26250522 10:11:16 6110008261 last price:6.2471 ErrorID[0] Message[] on_rsp_sub_market_data: instrument id["10088265"],6,true OnRtnDepthMarketData! [20250522 11:13:53 0]10008265 last price: 8.0776 OnRtnDepthMarketData! [20250522 11:13:53 010008265 last price: 6.8776 OnRtnDepthMarketData! [20250522 10:11:16 6]10008261 last price: 0.2471 OnRtnDepthMarketData! 10088261 last price: 0.2471[20250522 10:11:16 6] OnRtnDepthMarketData! [26250522 11:13:53 6110008265 last price: 8.0776 OnRtnDepthMarketData! [20250522 10:11:10 0] 10008261 last price: 0.2471 ``` -------------------------------- ### Create TraderApi Instance Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Initializes the TraderApi instance by providing the path to the dynamic library and the flow file directory. ```rust use ctp2rs::v1alpha1::TraderApi; // Linux 平台 #[cfg(target_os = "linux")] let dynlib_path = "./ctp-dyn/api/ctp/v6.7.2/v6.7.2_20230913_api_traderapi_se_linux64/thosttraderapi_se.so"; // 创建交易 API 实例 // 参数: 动态库路径, 流文件目录 let tdapi = TraderApi::create_api(dynlib_path, "./td_flow/"); println!("Trader API Version: {}", tdapi.get_api_version()); ``` -------------------------------- ### Channel Sample Output Log Source: https://github.com/pseudocodes/ctp2rs/blob/master/examples/channel/README.md This log displays the output from the channel sample, including connection events, subscription responses, and real-time market data updates. ```log [2024-12-10T03:05:09Z DEBUG channel] on_front_connected [2024-12-10T03:05:09Z DEBUG channel] on_rsp_user_login [2024-12-10T03:05:09Z DEBUG channel] on_rsp_sub_market_data [2024-12-10T03:05:09Z DEBUG channel] on_rsp_sub_market_data ErrorID[0] Message[CTP:No Error] [2024-12-10T03:05:09Z INFO channel] on_rsp_sub_market_data: ag2502 ErrorID[0] Message[CTP:No Error] [2024-12-10T03:05:09Z INFO channel] on_rsp_sub_market_data: fu2505 [2024-12-10T03:05:09Z INFO channel] 20241210 11:05:09 ag2502 last_price: 7942 [2024-12-10T03:05:09Z INFO channel] 20241210 11:05:08 fu2505 last_price: 3000 [2024-12-10T03:05:09Z INFO channel] 20241210 11:05:09 ag2502 last_price: 7941 [2024-12-10T03:05:10Z INFO channel] 20241210 11:05:10 ag2502 last_price: 7941 [2024-12-10T03:05:10Z INFO channel] 20241210 11:05:10 ag2502 last_price: 7941 [2024-12-10T03:05:10Z INFO channel] 20241210 11:05:11 ag2502 last_price: 7940 [2024-12-10T03:05:11Z INFO channel] 20241210 11:05:11 fu2505 last_price: 3000 ``` -------------------------------- ### Dynamically Load CTP API with Environment Variable Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Specify the CTP API include directory at build time using the CTP_API_INCLUDE_DIR environment variable. This allows for cross-version compatibility. ```shell > CTP_API_INCLUDE_DIR=/absolute/path/to/your/ctp/api/ cargo build ``` -------------------------------- ### MdApi::create_api Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Creates an instance of the market data API by loading the specified CTP dynamic library. ```APIDOC ## MdApi::create_api ### Description Creates an instance of the market data API (MdApi) by loading the CTP dynamic library from a specified path. ### Parameters - **dynlib_path** (string) - Required - Path to the CTP dynamic library (.so, .dll, or .framework). - **flow_path** (string) - Required - Directory path for storing flow files. - **use_udp** (bool) - Required - Whether to use UDP protocol. - **multicast** (bool) - Required - Whether to use multicast. ### Response - **MdApi** (object) - An instance of the market data API. ``` -------------------------------- ### Implement MdSpi for Market Data Subscription Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Implements the MdSpi trait to handle connection, login, and market data callbacks. Requires a channel for event communication between the callback thread and the main application. ```rust use std::sync::mpsc::{self, SyncSender}; use ctp2rs::ffi::{AssignFromString, WrapToString}; use ctp2rs::v1alpha1::*; // 实现行情回调接口 pub struct MyMdSpi { tx: SyncSender, } impl MdSpi for MyMdSpi { // 前置连接成功回调 fn on_front_connected(&mut self) { println!("前置连接成功"); self.tx.send(MdSpiEvent::OnFrontConnected( MdSpiOnFrontConnectedEvent {} )).unwrap(); } // 前置断开回调 fn on_front_disconnected(&mut self, reason: i32) { println!("前置断开, 原因: {}", reason); } // 登录响应回调 fn on_rsp_user_login( &mut self, rsp_user_login: Option<&CThostFtdcRspUserLoginField>, rsp_info: Option<&CThostFtdcRspInfoField>, request_id: i32, is_last: bool, ) { if let Some(info) = rsp_info { if info.ErrorID != 0 { println!("登录失败: {}", info.ErrorID); return; } } println!("登录成功"); self.tx.send(MdSpiEvent::OnRspUserLogin( MdSpiOnRspUserLoginEvent { rsp_user_login: rsp_user_login.cloned(), rsp_info: rsp_info.cloned(), request_id, is_last, } )).unwrap(); } // 订阅行情响应回调 fn on_rsp_sub_market_data( &mut self, specific_instrument: Option<&CThostFtdcSpecificInstrumentField>, rsp_info: Option<&CThostFtdcRspInfoField>, request_id: i32, is_last: bool, ) { if let Some(inst) = specific_instrument { println!("订阅成功: {}", inst.InstrumentID.to_string()); } } // 深度行情推送回调 fn on_rtn_depth_market_data( &mut self, depth_market_data: Option<&CThostFtdcDepthMarketDataField>, ) { if let Some(q) = depth_market_data { println!( "[{} {}] {} 最新价: {} 买一: {} 卖一: {}", q.ActionDay.to_string(), q.UpdateTime.to_string(), q.InstrumentID.to_string(), q.LastPrice, q.BidPrice1, q.AskPrice1 ); } } } fn main() { let mdapi = MdApi::create_api("./thostmduserapi_se.so", "./md_", false, false); let (tx, rx) = mpsc::sync_channel(1024); let mdspi = MyMdSpi { tx }; let mdspi_ptr = Box::into_raw(Box::new(mdspi)) as *mut dyn MdSpi; // 注册前置地址 (SimNow 模拟环境) mdapi.register_front("tcp://180.168.146.187:10131"); // 注册回调接口 mdapi.register_spi(mdspi_ptr); // 初始化 (启动网络线程) mdapi.init(); // 等待前置连接 if let Ok(MdSpiEvent::OnFrontConnected(_)) = rx.recv() { // 发送登录请求 let mut req = CThostFtdcReqUserLoginField::default(); req.BrokerID.assign_from_str("9999"); req.UserID.assign_from_str("你的用户名"); mdapi.req_user_login(&mut req, 1); } // 等待登录成功后订阅行情 if let Ok(MdSpiEvent::OnRspUserLogin(_)) = rx.recv() { let instruments = vec!["ag2512".to_string(), "au2512".to_string()]; mdapi.subscribe_market_data(&instruments); } // 持续接收行情 mdapi.join(); } ``` -------------------------------- ### Create MdApi instance with MdApiBuilder Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Use the builder pattern for more flexible configuration and explicit error handling. ```rust use ctp2rs::v1alpha1::MdApiBuilder; let mdapi = MdApiBuilder::new() .with_dynlib("./thostmduserapi_se.so") // 设置动态库路径 .flow_path("./md_flow/") // 设置流文件目录 .using_udp(false) // 不使用 UDP .multicast(false) // 不使用组播 .build() .expect("创建 MdApi 失败"); println!("API Version: {}", mdapi.get_api_version()); ``` -------------------------------- ### Create TraderApi with Builder Pattern Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Uses the TraderApiBuilder to configure and instantiate the TraderApi, providing a more fluent interface. ```rust use ctp2rs::v1alpha1::TraderApiBuilder; let tdapi = TraderApiBuilder::new() .with_dynlib("./thosttraderapi_se.so") .flow_path("./td_flow/") .build() .expect("创建 TraderApi 失败"); ``` -------------------------------- ### Add Ctp2rs to Project Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Add the ctp2rs crate to your project using Cargo or by manually editing Cargo.toml. ```shell cargo add ctp2rs ``` ```toml [dependencies] ctp2rs = "0.1" ``` ```toml [dependencies] ctp2rs = { git = "https://github.com/pseudocodes/ctp2rs", package = "ctp2rs" } ``` -------------------------------- ### Environment Variable for CTP Header Files Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Specify custom CTP API header files during build time using the `CTP_API_INCLUDE_DIR` environment variable. Ensure header files are UTF-8 encoded. ```bash # 使用自定义 CTP API 版本构建 CTP_API_INCLUDE_DIR=/path/to/your/ctp/api/ cargo build # 注意: 头文件需要转码为 UTF-8 ``` -------------------------------- ### Feature Toggles for CTP Version Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Configure the CTP version dependency at compile time using Cargo features. Multiple CTP versions and CTP-Mini are supported. ```toml [dependencies] # 默认版本 v6.7.2 ctp2rs = "0.1" # 指定 v6.7.7 版本 ctp2rs = { version = "0.1", features = ["ctp_v6_7_7"] } # 指定 v6.7.11 版本 (合并生产和评测) ctp2rs = { version = "0.1.8-alpha1", features = ["ctp_v6_7_11"] } # CTP-Mini 迷你版本 ctp2rs = { version = "0.1", features = ["mini_v1_7_0"] } # CTP-Sopt 股票期权版本 ctp2rs = { version = "0.1", features = ["sopt_v3_7_3"] } ``` -------------------------------- ### MdApiBuilder Source: https://context7.com/pseudocodes/ctp2rs/llms.txt A builder pattern implementation for configuring and creating an MdApi instance with error handling. ```APIDOC ## MdApiBuilder ### Description Provides a builder pattern to configure and instantiate the MdApi, allowing for safer error handling compared to direct creation. ### Methods - **with_dynlib(path)** - Sets the path to the dynamic library. - **flow_path(path)** - Sets the directory for flow files. - **using_udp(bool)** - Configures UDP usage. - **multicast(bool)** - Configures multicast usage. - **build()** - Returns a Result containing the MdApi instance or an error. ``` -------------------------------- ### Specify CTP API Version with Features Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/README.md Select a specific CTP API version by enabling the corresponding feature in Cargo.toml. This is necessary for versions like v6.7.11 that have different initialization parameters. ```toml [dependencies] ctp2rs = { version = "0.1", features = ["ctp_v6_7_7"] } ``` ```toml [dependencies] ctp2rs = { version = "0.1.8-alpha1", features = ["ctp_v6_7_11"] } ``` -------------------------------- ### Import Thost Trader API Header Source: https://github.com/pseudocodes/ctp2rs/blob/master/ctp-dyn/api/ctp/v6.7.7/v6.7.7_MacOS_20240716/README.txt Modify the import statement to correctly reference the Thost Trader API header file. This is crucial for resolving 'header file not found' errors. ```objective-c #import "thosttraderapi_se/ThostFtdcTraderApi.h" ``` -------------------------------- ### Add Ctp2rs dependency in Cargo.toml Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Include the library in your project dependencies, optionally specifying a feature for a specific CTP version. ```toml [dependencies] ctp2rs = "0.1" # 或指定特定版本 ctp2rs = { version = "0.1", features = ["ctp_v6_7_7"] } ``` -------------------------------- ### Implement TraderSpi for Full Trading Flow Source: https://context7.com/pseudocodes/ctp2rs/llms.txt Implement the TraderSpi trait to handle various trading callbacks such as front connection, authentication response, user login, settlement confirmation, position query, order notifications, and trade notifications. This struct manages the TraderApi instance and a request ID counter. ```rust use std::sync::Arc; use ctp2rs::ffi::{AssignFromString, WrapToString}; use ctp2rs::v1alpha1::*; pub struct MyTraderSpi { pub tdapi: Arc, pub request_id: i32, } impl TraderSpi for MyTraderSpi { // 前置连接成功 fn on_front_connected(&mut self) { println!("交易前置连接成功"); // 发送客户端认证请求 let mut req = CThostFtdcReqAuthenticateField::default(); req.BrokerID.assign_from_str("9999"); req.UserID.assign_from_str("你的用户名"); req.AppID.assign_from_str("simnow_client_test"); req.AuthCode.assign_from_str("0000000000000000"); self.request_id += 1; self.tdapi.req_authenticate(&mut req, self.request_id); } // 认证响应 fn on_rsp_authenticate( &mut self, _p_rsp_authenticate: Option<&CThostFtdcRspAuthenticateField>, p_rsp_info: Option<&CThostFtdcRspInfoField>, _n_request_id: i32, b_is_last: bool, ) { if let Some(info) = p_rsp_info { if info.ErrorID != 0 { println!("认证失败: {}", info.ErrorID); return; } } if b_is_last { println!("认证成功,开始登录"); let mut req = CThostFtdcReqUserLoginField::default(); req.BrokerID.assign_from_str("9999"); req.UserID.assign_from_str("你的用户名"); req.Password.assign_from_str("你的密码"); self.request_id += 1; self.tdapi.req_user_login(&mut req, self.request_id); } } // 登录响应 fn on_rsp_user_login( &mut self, _p_rsp_user_login: Option<&CThostFtdcRspUserLoginField>, p_rsp_info: Option<&CThostFtdcRspInfoField>, _n_request_id: i32, b_is_last: bool, ) { if let Some(info) = p_rsp_info { if info.ErrorID != 0 { println!("登录失败: {}", info.ErrorID); return; } } if b_is_last { println!("登录成功,确认结算单"); let mut req = CThostFtdcSettlementInfoConfirmField::default(); req.BrokerID.assign_from_str("9999"); req.InvestorID.assign_from_str("你的用户名"); self.request_id += 1; self.tdapi.req_settlement_info_confirm(&mut req, self.request_id); } } // 结算单确认响应 fn on_rsp_settlement_info_confirm( &mut self, _p_settlement_info_confirm: Option<&CThostFtdcSettlementInfoConfirmField>, _p_rsp_info: Option<&CThostFtdcRspInfoField>, _n_request_id: i32, b_is_last: bool, ) { if b_is_last { println!("结算单确认完成,查询持仓"); // 等待 1 秒避免流控 std::thread::sleep(std::time::Duration::from_secs(1)); let mut req = CThostFtdcQryInvestorPositionField::default(); self.request_id += 1; self.tdapi.req_qry_investor_position(&mut req, self.request_id); } } // 持仓查询响应 fn on_rsp_qry_investor_position( &mut self, p_investor_position: Option<&CThostFtdcInvestorPositionField>, _p_rsp_info: Option<&CThostFtdcRspInfoField>, _n_request_id: i32, b_is_last: bool, ) { if let Some(pos) = p_investor_position { println!( "持仓: {} 方向: {} 数量: {}", pos.InstrumentID.to_string(), pos.PosiDirection, pos.Position ); } if b_is_last { println!("持仓查询完成"); } } // 报单通知 fn on_rtn_order(&mut self, p_order: Option<&CThostFtdcOrderField>) { if let Some(order) = p_order { println!( "报单回报: {} {} {} 状态: ?", order.InstrumentID.to_string(), order.Direction, order.VolumeTotalOriginal, order.OrderStatus ); } } // 成交通知 fn on_rtn_trade(&mut self, p_trade: Option<&CThostFtdcTradeField>) { if let Some(trade) = p_trade { println!( "成交回报: {} {} {} 价格: {}", trade.InstrumentID.to_string(), trade.Direction, trade.Volume, trade.Price ); } } } ``` ```rust fn main() { let tdapi = TraderApi::create_api("./thosttraderapi_se.so", "./td_"); let tdapi = Arc::new(tdapi); let tdspi = MyTraderSpi { tdapi: Arc::clone(&tdapi), request_id: 0, }; let tdspi_ptr = Box::into_raw(Box::new(tdspi)); // 注册前置地址 (SimNow 交易环境) tdapi.register_front("tcp://180.168.146.187:10130"); // 注册回调 tdapi.register_spi(tdspi_ptr); // 订阅私有流和公共流 tdapi.subscribe_private_topic(THOST_TE_RESUME_TYPE::THOST_TERT_QUICK); tdapi.subscribe_public_topic(THOST_TE_RESUME_TYPE::THOST_TERT_QUICK); // 初始化 tdapi.init(); // 等待线程结束 loop { std::thread::sleep(std::time::Duration::from_secs(10)); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.