1use crate::api::md_api::DepthMarketDataField;
6use crate::api::{safe_cstr_to_string, to_cstring, CtpApi};
7use crate::error::{CtpError, CtpResult};
8use crate::ffi::trader_api::*;
9use crate::ffi::{CreateTraderSpiBridge, TraderSpiCallbacks};
10use crate::types::{
11 ExchangeField, InputBatchOrderActionField, InputExecOrderActionField, InputExecOrderField,
12 InputForQuoteField, InputOrderActionField, InputQuoteActionField, InputQuoteField,
13 InstrumentCommissionRateField, InstrumentMarginRateField, InvestorPositionDetailField,
14 NoticeField, OrderActionField, ParkedOrderActionField, ParkedOrderField, ProductField,
15 QryDepthMarketDataField, QryExchangeField, QryInstrumentCommissionRateField,
16 QryInstrumentField, QryInstrumentMarginRateField, QryInvestorPositionDetailField,
17 QryInvestorPositionField, QryMaxOrderVolumeField, QryNoticeField, QryOrderField,
18 QryProductField, QrySettlementInfoField, QryTradeField, QryTradingAccountField,
19 QryTransferBankField, RemoveParkedOrderActionField, RemoveParkedOrderField, ReqUserLoginField,
20 RspInfoField, RspUserLoginField, SettlementInfoConfirmField, SettlementInfoField,
21 TransferBankField,
22};
23use std::ffi::c_void;
24use std::os::raw::c_int;
25use std::ptr;
26use std::sync::{Arc, Mutex};
27
28#[allow(dead_code)]
30pub struct TraderApi {
31 api_ptr: *mut c_void,
33 spi_ptr: *mut c_void,
35 initialized: bool,
37 request_id: Arc<Mutex<i32>>,
39 handler: Option<Box<dyn TraderSpiHandler + Send + Sync>>,
41}
42
43#[allow(unused_variables)]
45pub trait TraderSpiHandler {
46 fn on_front_connected(&mut self) {}
48
49 fn on_front_disconnected(&mut self, reason: i32) {}
51
52 fn on_heart_beat_warning(&mut self, time_lapse: i32) {}
54
55 fn on_rsp_authenticate(
57 &mut self,
58 rsp_authenticate: Option<RspAuthenticateField>,
59 rsp_info: Option<RspInfoField>,
60 request_id: i32,
61 is_last: bool,
62 ) {
63 }
64
65 fn on_rsp_user_login(
67 &mut self,
68 user_login: Option<RspUserLoginField>,
69 rsp_info: Option<RspInfoField>,
70 request_id: i32,
71 is_last: bool,
72 ) {
73 }
74
75 fn on_rsp_user_logout(
77 &mut self,
78 user_logout: Option<()>,
79 rsp_info: Option<RspInfoField>,
80 request_id: i32,
81 is_last: bool,
82 ) {
83 }
84
85 fn on_rsp_error(&mut self, rsp_info: Option<RspInfoField>, request_id: i32, is_last: bool) {}
87
88 fn on_rsp_order_insert(
90 &mut self,
91 input_order: Option<InputOrderField>,
92 rsp_info: Option<RspInfoField>,
93 request_id: i32,
94 is_last: bool,
95 ) {
96 }
97
98 fn on_rsp_order_action(
100 &mut self,
101 input_order_action: Option<InputOrderActionField>,
102 rsp_info: Option<RspInfoField>,
103 request_id: i32,
104 is_last: bool,
105 ) {
106 }
107
108 fn on_rtn_order(&mut self, order: OrderField) {}
110
111 fn on_rtn_trade(&mut self, trade: TradeField) {}
113
114 fn on_rsp_qry_investor(
116 &mut self,
117 investor: Option<InvestorField>,
118 rsp_info: Option<RspInfoField>,
119 request_id: i32,
120 is_last: bool,
121 ) {
122 }
123
124 fn on_rsp_qry_trading_account(
126 &mut self,
127 trading_account: Option<TradingAccountField>,
128 rsp_info: Option<RspInfoField>,
129 request_id: i32,
130 is_last: bool,
131 ) {
132 }
133
134 fn on_rsp_qry_investor_position(
136 &mut self,
137 investor_position: Option<InvestorPositionField>,
138 rsp_info: Option<RspInfoField>,
139 request_id: i32,
140 is_last: bool,
141 ) {
142 }
143
144 fn on_rsp_qry_instrument(
146 &mut self,
147 instrument: Option<InstrumentField>,
148 rsp_info: Option<RspInfoField>,
149 request_id: i32,
150 is_last: bool,
151 ) {
152 }
153
154 fn on_err_rtn_order_insert(
158 &mut self,
159 input_order: Option<InputOrderField>,
160 rsp_info: Option<RspInfoField>,
161 ) {
162 }
163
164 fn on_err_rtn_order_action(
166 &mut self,
167 order_action: Option<OrderActionField>,
168 rsp_info: Option<RspInfoField>,
169 ) {
170 }
171
172 fn on_rsp_qry_order(
174 &mut self,
175 order: Option<OrderField>,
176 rsp_info: Option<RspInfoField>,
177 request_id: i32,
178 is_last: bool,
179 ) {
180 }
181
182 fn on_rsp_qry_trade(
184 &mut self,
185 trade: Option<TradeField>,
186 rsp_info: Option<RspInfoField>,
187 request_id: i32,
188 is_last: bool,
189 ) {
190 }
191
192 fn on_rsp_qry_instrument_margin_rate(
196 &mut self,
197 margin_rate: Option<InstrumentMarginRateField>,
198 rsp_info: Option<RspInfoField>,
199 request_id: i32,
200 is_last: bool,
201 ) {
202 }
203
204 fn on_rsp_qry_instrument_commission_rate(
206 &mut self,
207 commission_rate: Option<InstrumentCommissionRateField>,
208 rsp_info: Option<RspInfoField>,
209 request_id: i32,
210 is_last: bool,
211 ) {
212 }
213
214 fn on_rsp_qry_exchange(
216 &mut self,
217 exchange: Option<ExchangeField>,
218 rsp_info: Option<RspInfoField>,
219 request_id: i32,
220 is_last: bool,
221 ) {
222 }
223
224 fn on_rsp_qry_product(
226 &mut self,
227 product: Option<ProductField>,
228 rsp_info: Option<RspInfoField>,
229 request_id: i32,
230 is_last: bool,
231 ) {
232 }
233
234 fn on_rsp_settlement_info_confirm(
236 &mut self,
237 settlement_info_confirm: Option<SettlementInfoConfirmField>,
238 rsp_info: Option<RspInfoField>,
239 request_id: i32,
240 is_last: bool,
241 ) {
242 }
243
244 fn on_rsp_parked_order_insert(
246 &mut self,
247 parked_order: Option<ParkedOrderField>,
248 rsp_info: Option<RspInfoField>,
249 request_id: i32,
250 is_last: bool,
251 ) {
252 }
253
254 fn on_rsp_parked_order_action(
256 &mut self,
257 parked_order_action: Option<ParkedOrderActionField>,
258 rsp_info: Option<RspInfoField>,
259 request_id: i32,
260 is_last: bool,
261 ) {
262 }
263
264 fn on_rsp_exec_order_insert(
268 &mut self,
269 input_exec_order: Option<InputExecOrderField>,
270 rsp_info: Option<RspInfoField>,
271 request_id: i32,
272 is_last: bool,
273 ) {
274 }
275
276 fn on_rsp_exec_order_action(
278 &mut self,
279 input_exec_order_action: Option<InputExecOrderActionField>,
280 rsp_info: Option<RspInfoField>,
281 request_id: i32,
282 is_last: bool,
283 ) {
284 }
285
286 fn on_rsp_for_quote_insert(
288 &mut self,
289 input_for_quote: Option<InputForQuoteField>,
290 rsp_info: Option<RspInfoField>,
291 request_id: i32,
292 is_last: bool,
293 ) {
294 }
295
296 fn on_rsp_quote_insert(
298 &mut self,
299 input_quote: Option<InputQuoteField>,
300 rsp_info: Option<RspInfoField>,
301 request_id: i32,
302 is_last: bool,
303 ) {
304 }
305
306 fn on_rsp_quote_action(
308 &mut self,
309 input_quote_action: Option<InputQuoteActionField>,
310 rsp_info: Option<RspInfoField>,
311 request_id: i32,
312 is_last: bool,
313 ) {
314 }
315
316 fn on_rsp_batch_order_action(
318 &mut self,
319 input_batch_order_action: Option<InputBatchOrderActionField>,
320 rsp_info: Option<RspInfoField>,
321 request_id: i32,
322 is_last: bool,
323 ) {
324 }
325
326 fn on_rsp_remove_parked_order(
328 &mut self,
329 remove_parked_order: Option<RemoveParkedOrderField>,
330 rsp_info: Option<RspInfoField>,
331 request_id: i32,
332 is_last: bool,
333 ) {
334 }
335
336 fn on_rsp_remove_parked_order_action(
338 &mut self,
339 remove_parked_order_action: Option<RemoveParkedOrderActionField>,
340 rsp_info: Option<RspInfoField>,
341 request_id: i32,
342 is_last: bool,
343 ) {
344 }
345
346 fn on_rsp_qry_max_order_volume(
348 &mut self,
349 qry_max_order_volume: Option<QryMaxOrderVolumeField>,
350 rsp_info: Option<RspInfoField>,
351 request_id: i32,
352 is_last: bool,
353 ) {
354 }
355
356 fn on_rsp_qry_depth_market_data(
358 &mut self,
359 depth_market_data: Option<DepthMarketDataField>,
360 rsp_info: Option<RspInfoField>,
361 request_id: i32,
362 is_last: bool,
363 ) {
364 }
365
366 fn on_rsp_qry_settlement_info(
368 &mut self,
369 settlement_info: Option<SettlementInfoField>,
370 rsp_info: Option<RspInfoField>,
371 request_id: i32,
372 is_last: bool,
373 ) {
374 }
375
376 fn on_rsp_qry_transfer_bank(
378 &mut self,
379 transfer_bank: Option<TransferBankField>,
380 rsp_info: Option<RspInfoField>,
381 request_id: i32,
382 is_last: bool,
383 ) {
384 }
385
386 fn on_rsp_qry_investor_position_detail(
388 &mut self,
389 investor_position_detail: Option<InvestorPositionDetailField>,
390 rsp_info: Option<RspInfoField>,
391 request_id: i32,
392 is_last: bool,
393 ) {
394 }
395
396 fn on_rsp_qry_notice(
398 &mut self,
399 notice: Option<NoticeField>,
400 rsp_info: Option<RspInfoField>,
401 request_id: i32,
402 is_last: bool,
403 ) {
404 }
405}
406
407#[repr(C)]
409#[derive(Debug, Clone)]
410pub struct RspAuthenticateField {
411 pub broker_id: [u8; 11],
413 pub user_id: [u8; 16],
415 pub user_product_info: [u8; 11],
417 pub app_id: [u8; 33],
419 pub app_type: u8,
421}
422
423impl Default for RspAuthenticateField {
424 fn default() -> Self {
425 unsafe { std::mem::zeroed() }
426 }
427}
428
429#[repr(C)]
431#[derive(Debug, Clone)]
432pub struct InputOrderField {
433 pub broker_id: [u8; 11],
435 pub investor_id: [u8; 13],
437 pub instrument_id: [u8; 31],
439 pub order_ref: [u8; 13],
441 pub user_id: [u8; 16],
443 pub order_price_type: u8,
445 pub direction: u8,
447 pub comb_offset_flag: [u8; 5],
449 pub comb_hedge_flag: [u8; 5],
451 pub limit_price: f64,
453 pub volume_total_original: i32,
455 pub time_condition: u8,
457 pub gtd_date: [u8; 9],
459 pub volume_condition: u8,
461 pub min_volume: i32,
463 pub contingent_condition: u8,
465 pub stop_price: f64,
467 pub force_close_reason: u8,
469 pub is_auto_suspend: i32,
471 pub business_unit: [u8; 21],
473 pub request_id: i32,
475 pub user_force_close: i32,
477 pub is_swap_order: i32,
479 pub exchange_id: [u8; 9],
481 pub invest_unit_id: [u8; 17],
483 pub account_id: [u8; 13],
485 pub currency_id: [u8; 4],
487 pub client_id: [u8; 11],
489 pub mac_address: [u8; 21],
491 pub exchange_inst_id: [u8; 31],
493 pub ip_address: [u8; 16],
495}
496
497impl Default for InputOrderField {
498 fn default() -> Self {
499 unsafe { std::mem::zeroed() }
500 }
501}
502
503#[repr(C)]
505#[derive(Debug, Clone)]
506pub struct OrderField {
507 pub broker_id: [u8; 11],
509 pub investor_id: [u8; 13],
511 pub instrument_id: [u8; 31],
513 pub order_ref: [u8; 13],
515 pub user_id: [u8; 16],
517 pub order_price_type: u8,
519 pub direction: u8,
521 pub comb_offset_flag: [u8; 5],
523 pub comb_hedge_flag: [u8; 5],
525 pub limit_price: f64,
527 pub volume_total_original: i32,
529 pub time_condition: u8,
531 pub gtd_date: [u8; 9],
533 pub volume_condition: u8,
535 pub min_volume: i32,
537 pub contingent_condition: u8,
539 pub stop_price: f64,
541 pub force_close_reason: u8,
543 pub is_auto_suspend: i32,
545 pub business_unit: [u8; 21],
547 pub request_id: i32,
549 pub order_local_id: [u8; 13],
551 pub exchange_id: [u8; 9],
553 pub participant_id: [u8; 11],
555 pub client_id: [u8; 11],
557 pub exchange_inst_id: [u8; 31],
559 pub trader_id: [u8; 21],
561 pub install_id: i32,
563 pub order_submit_status: u8,
565 pub notify_sequence: i32,
567 pub trading_day: [u8; 9],
569 pub settlement_id: i32,
571 pub order_sys_id: [u8; 21],
573 pub order_source: u8,
575 pub order_status: u8,
577 pub order_type: u8,
579 pub volume_traded: i32,
581 pub volume_total: i32,
583 pub insert_date: [u8; 9],
585 pub insert_time: [u8; 9],
587 pub active_time: [u8; 9],
589 pub suspend_time: [u8; 9],
591 pub update_time: [u8; 9],
593 pub cancel_time: [u8; 9],
595 pub active_trader_id: [u8; 21],
597 pub clearing_part_id: [u8; 11],
599 pub sequence_no: i32,
601 pub front_id: i32,
603 pub session_id: i32,
605 pub user_product_info: [u8; 11],
607 pub status_msg: [u8; 81],
609 pub user_force_close: i32,
611 pub active_user_id: [u8; 16],
613 pub broker_order_seq: i32,
615 pub relative_order_sys_id: [u8; 21],
617 pub zczc_total_traded_volume: i32,
619 pub is_swap_order: i32,
621 pub branch_id: [u8; 9],
623 pub invest_unit_id: [u8; 17],
625 pub account_id: [u8; 13],
627 pub currency_id: [u8; 4],
629 pub mac_address: [u8; 21],
631 pub ip_address: [u8; 16],
633}
634
635impl Default for OrderField {
636 fn default() -> Self {
637 unsafe { std::mem::zeroed() }
638 }
639}
640
641#[repr(C)]
643#[derive(Debug, Clone)]
644pub struct TradeField {
645 pub broker_id: [u8; 11],
647 pub investor_id: [u8; 13],
649 pub instrument_id: [u8; 31],
651 pub order_ref: [u8; 13],
653 pub user_id: [u8; 16],
655 pub exchange_id: [u8; 9],
657 pub trade_id: [u8; 21],
659 pub direction: u8,
661 pub order_sys_id: [u8; 21],
663 pub participant_id: [u8; 11],
665 pub client_id: [u8; 11],
667 pub trading_role: u8,
669 pub exchange_inst_id: [u8; 31],
671 pub offset_flag: u8,
673 pub hedge_flag: u8,
675 pub price: f64,
677 pub volume: i32,
679 pub trade_date: [u8; 9],
681 pub trade_time: [u8; 9],
683 pub trade_type: u8,
685 pub price_source: u8,
687 pub trader_id: [u8; 21],
689 pub order_local_id: [u8; 13],
691 pub clearing_part_id: [u8; 11],
693 pub business_unit: [u8; 21],
695 pub sequence_no: i32,
697 pub trading_day: [u8; 9],
699 pub settlement_id: i32,
701 pub broker_order_seq: i32,
703 pub trade_source: u8,
705 pub invest_unit_id: [u8; 17],
707}
708
709impl Default for TradeField {
710 fn default() -> Self {
711 unsafe { std::mem::zeroed() }
712 }
713}
714
715#[repr(C)]
717#[derive(Debug, Clone)]
718pub struct InvestorField {
719 pub investor_id: [u8; 13],
721 pub broker_id: [u8; 11],
723 pub investor_group_id: [u8; 13],
725 pub investor_name: [u8; 81],
727 pub identity_card_type: u8,
729 pub identity_card_no: [u8; 51],
731 pub is_active: i32,
733 pub telephone: [u8; 41],
735 pub address: [u8; 101],
737 pub open_date: [u8; 9],
739 pub mobile: [u8; 41],
741 pub comm_model_id: [u8; 13],
743 pub margin_model_id: [u8; 13],
745}
746
747impl Default for InvestorField {
748 fn default() -> Self {
749 unsafe { std::mem::zeroed() }
750 }
751}
752
753#[repr(C)]
755#[derive(Debug, Clone)]
756pub struct TradingAccountField {
757 pub broker_id: [u8; 11],
759 pub account_id: [u8; 13],
761 pub pre_mortgage: f64,
763 pub pre_credit: f64,
765 pub pre_deposit: f64,
767 pub pre_balance: f64,
769 pub pre_margin: f64,
771 pub interest_base: f64,
773 pub interest: f64,
775 pub deposit: f64,
777 pub withdraw: f64,
779 pub frozen_margin: f64,
781 pub frozen_cash: f64,
783 pub frozen_commission: f64,
785 pub curr_margin: f64,
787 pub cash_in: f64,
789 pub commission: f64,
791 pub close_profit: f64,
793 pub position_profit: f64,
795 pub balance: f64,
797 pub available: f64,
799 pub withdraw_quota: f64,
801 pub reserve: f64,
803 pub trading_day: [u8; 9],
805 pub settlement_id: i32,
807 pub credit: f64,
809 pub mortgage: f64,
811 pub exchange_margin: f64,
813 pub delivery_margin: f64,
815 pub exchange_delivery_margin: f64,
817 pub reserve_balance: f64,
819 pub currency_id: [u8; 4],
821 pub pre_fund_mortgage_in: f64,
823 pub pre_fund_mortgage_out: f64,
825 pub fund_mortgage_in: f64,
827 pub fund_mortgage_out: f64,
829 pub fund_mortgage_available: f64,
831 pub mortgageable_fund: f64,
833 pub spec_product_margin: f64,
835 pub spec_product_frozen_margin: f64,
837 pub spec_product_commission: f64,
839 pub spec_product_frozen_commission: f64,
841 pub spec_product_position_profit: f64,
843 pub spec_product_close_profit: f64,
845 pub spec_product_position_profit_by_alg: f64,
847 pub spec_product_exchange_margin: f64,
849 pub biz_type: u8,
851 pub frozen_swap: f64,
853 pub remain_swap: f64,
855}
856
857impl Default for TradingAccountField {
858 fn default() -> Self {
859 unsafe { std::mem::zeroed() }
860 }
861}
862
863#[repr(C)]
865#[derive(Debug, Clone)]
866pub struct InvestorPositionField {
867 pub instrument_id: [u8; 31],
869 pub broker_id: [u8; 11],
871 pub investor_id: [u8; 13],
873 pub posi_direction: u8,
875 pub hedge_flag: u8,
877 pub position_date: u8,
879 pub yd_position: i32,
881 pub position: i32,
883 pub long_frozen: i32,
885 pub short_frozen: i32,
887 pub long_frozen_amount: f64,
889 pub short_frozen_amount: f64,
891 pub open_volume: i32,
893 pub close_volume: i32,
895 pub open_amount: f64,
897 pub close_amount: f64,
899 pub position_cost: f64,
901 pub pre_margin: f64,
903 pub use_margin: f64,
905 pub frozen_margin: f64,
907 pub frozen_cash: f64,
909 pub frozen_commission: f64,
911 pub cash_in: f64,
913 pub commission: f64,
915 pub close_profit: f64,
917 pub position_profit: f64,
919 pub pre_settlement_price: f64,
921 pub settlement_price: f64,
923 pub trading_day: [u8; 9],
925 pub settlement_id: i32,
927 pub open_cost: f64,
929 pub exchange_margin: f64,
931 pub comb_position: i32,
933 pub comb_long_frozen: i32,
935 pub comb_short_frozen: i32,
937 pub close_profit_by_date: f64,
939 pub close_profit_by_trade: f64,
941 pub today_position: i32,
943 pub margin_rate_by_money: f64,
945 pub margin_rate_by_volume: f64,
947 pub strike_frozen: i32,
949 pub strike_frozen_amount: f64,
951 pub abandon_frozen: i32,
953 pub exchange_id: [u8; 9],
955 pub yd_strike_frozen: i32,
957 pub invest_unit_id: [u8; 17],
959 pub position_cost_offset: f64,
961 pub tas_position: i32,
963 pub tas_position_cost: f64,
965}
966
967impl Default for InvestorPositionField {
968 fn default() -> Self {
969 unsafe { std::mem::zeroed() }
970 }
971}
972
973#[repr(C)]
975#[derive(Debug, Clone)]
976pub struct InstrumentField {
977 pub instrument_id: [u8; 31],
979 pub exchange_id: [u8; 9],
981 pub instrument_name: [u8; 21],
983 pub exchange_inst_id: [u8; 31],
985 pub product_id: [u8; 31],
987 pub product_class: u8,
989 pub delivery_year: i32,
991 pub delivery_month: i32,
993 pub max_market_order_volume: i32,
995 pub min_market_order_volume: i32,
997 pub max_limit_order_volume: i32,
999 pub min_limit_order_volume: i32,
1001 pub volume_multiple: i32,
1003 pub price_tick: f64,
1005 pub create_date: [u8; 9],
1007 pub open_date: [u8; 9],
1009 pub expire_date: [u8; 9],
1011 pub start_deliv_date: [u8; 9],
1013 pub end_deliv_date: [u8; 9],
1015 pub inst_life_phase: u8,
1017 pub is_trading: i32,
1019 pub position_type: u8,
1021 pub position_date_type: u8,
1023 pub long_margin_ratio: f64,
1025 pub short_margin_ratio: f64,
1027 pub max_margin_side_algorithm: u8,
1029 pub underlying_instr_id: [u8; 31],
1031 pub strike_price: f64,
1033 pub options_type: u8,
1035 pub underlying_multiple: f64,
1037 pub combination_type: u8,
1039}
1040
1041impl Default for InstrumentField {
1042 fn default() -> Self {
1043 unsafe { std::mem::zeroed() }
1044 }
1045}
1046
1047unsafe impl Send for TraderApi {}
1048unsafe impl Sync for TraderApi {}
1049
1050impl TraderApi {
1051 pub fn new(flow_path: Option<&str>, is_production_mode: Option<bool>) -> CtpResult<Self> {
1057 let flow_path_cstr = match flow_path {
1058 Some(path) => Some(to_cstring(path)?),
1059 None => None,
1060 };
1061
1062 let flow_path_ptr = flow_path_cstr
1063 .as_ref()
1064 .map(|s| s.as_ptr())
1065 .unwrap_or(ptr::null());
1066
1067 let production_mode = is_production_mode.unwrap_or(true);
1068
1069 let api_ptr =
1070 unsafe { CThostFtdcTraderApi_CreateFtdcTraderApi(flow_path_ptr, production_mode) };
1071
1072 if api_ptr.is_null() {
1073 return Err(CtpError::InitializationError("创建交易API失败".to_string()));
1074 }
1075
1076 Ok(TraderApi {
1077 api_ptr,
1078 spi_ptr: ptr::null_mut(),
1079 initialized: false,
1080 request_id: Arc::new(Mutex::new(1)),
1081 handler: None,
1082 })
1083 }
1084
1085 pub fn register_spi<T>(&mut self, handler: T) -> CtpResult<()>
1087 where
1088 T: TraderSpiHandler + Send + Sync + 'static,
1089 {
1090 self.handler = Some(Box::new(handler));
1091
1092 let callbacks = TraderSpiCallbacks {
1094 user_data: self as *mut _ as *mut c_void,
1095 on_front_connected: Some(on_front_connected_callback),
1096 on_front_disconnected: Some(on_front_disconnected_callback),
1097 on_heart_beat_warning: Some(on_heart_beat_warning_callback),
1098 on_rsp_authenticate: Some(on_rsp_authenticate_callback),
1099 on_rsp_user_login: Some(on_rsp_user_login_callback),
1100 on_rsp_user_logout: Some(on_rsp_user_logout_callback),
1101 on_rsp_error: Some(on_rsp_error_callback),
1102 on_rsp_order_insert: Some(on_rsp_order_insert_callback),
1103 on_rsp_order_action: Some(on_rsp_order_action_callback),
1104 on_rtn_order: Some(on_rtn_order_callback),
1105 on_rtn_trade: Some(on_rtn_trade_callback),
1106 on_rsp_qry_trading_account: Some(on_rsp_qry_trading_account_callback),
1107 on_rsp_qry_investor_position: Some(on_rsp_qry_investor_position_callback),
1108
1109 on_err_rtn_order_insert: Some(on_err_rtn_order_insert_callback),
1111 on_err_rtn_order_action: Some(on_err_rtn_order_action_callback),
1112 on_rsp_qry_order: Some(on_rsp_qry_order_callback),
1113 on_rsp_qry_trade: Some(on_rsp_qry_trade_callback),
1114 on_rsp_qry_instrument: Some(on_rsp_qry_instrument_callback),
1115
1116 on_rsp_qry_instrument_margin_rate: Some(on_rsp_qry_instrument_margin_rate_callback),
1118 on_rsp_qry_instrument_commission_rate: Some(
1119 on_rsp_qry_instrument_commission_rate_callback,
1120 ),
1121 on_rsp_qry_exchange: Some(on_rsp_qry_exchange_callback),
1122 on_rsp_qry_product: Some(on_rsp_qry_product_callback),
1123 on_rsp_settlement_info_confirm: Some(on_rsp_settlement_info_confirm_callback),
1124 on_rsp_parked_order_insert: Some(on_rsp_parked_order_insert_callback),
1125 on_rsp_parked_order_action: Some(on_rsp_parked_order_action_callback),
1126
1127 on_rsp_exec_order_insert: Some(on_rsp_exec_order_insert_callback),
1129 on_rsp_exec_order_action: Some(on_rsp_exec_order_action_callback),
1130 on_rsp_for_quote_insert: Some(on_rsp_for_quote_insert_callback),
1131 on_rsp_quote_insert: Some(on_rsp_quote_insert_callback),
1132 on_rsp_quote_action: Some(on_rsp_quote_action_callback),
1133 on_rsp_batch_order_action: Some(on_rsp_batch_order_action_callback),
1134 on_rsp_remove_parked_order: Some(on_rsp_remove_parked_order_callback),
1135 on_rsp_remove_parked_order_action: Some(on_rsp_remove_parked_order_action_callback),
1136 on_rsp_qry_max_order_volume: Some(on_rsp_qry_max_order_volume_callback),
1137 on_rsp_qry_depth_market_data: Some(on_rsp_qry_depth_market_data_callback),
1138 on_rsp_qry_settlement_info: Some(on_rsp_qry_settlement_info_callback),
1139 on_rsp_qry_transfer_bank: Some(on_rsp_qry_transfer_bank_callback),
1140 on_rsp_qry_investor_position_detail: Some(on_rsp_qry_investor_position_detail_callback),
1141 on_rsp_qry_notice: Some(on_rsp_qry_notice_callback),
1142 };
1143
1144 self.spi_ptr = unsafe { CreateTraderSpiBridge(&callbacks) };
1146
1147 if self.spi_ptr.is_null() {
1148 return Err(CtpError::InitializationError(
1149 "创建交易SPI桥接器失败".to_string(),
1150 ));
1151 }
1152
1153 unsafe {
1155 CThostFtdcTraderApi_RegisterSpi(self.api_ptr, self.spi_ptr);
1156 }
1157
1158 Ok(())
1159 }
1160
1161 pub fn req_authenticate(&mut self, req: &ReqAuthenticateField) -> CtpResult<i32> {
1163 if self.api_ptr.is_null() {
1164 return Err(CtpError::InitializationError("API未初始化".to_string()));
1165 }
1166
1167 let request_id = self.next_request_id();
1168
1169 let result = unsafe {
1170 CThostFtdcTraderApi_ReqAuthenticate(
1171 self.api_ptr,
1172 req as *const _ as *const c_void,
1173 request_id,
1174 )
1175 };
1176
1177 if result != 0 {
1178 return Err(CtpError::FfiError(format!("认证请求失败: {}", result)));
1179 }
1180
1181 Ok(request_id)
1182 }
1183
1184 pub fn req_user_login(&mut self, req: &ReqUserLoginField) -> CtpResult<i32> {
1186 if self.api_ptr.is_null() {
1187 return Err(CtpError::InitializationError("API未初始化".to_string()));
1188 }
1189
1190 let request_id = self.next_request_id();
1191
1192 let result = unsafe {
1193 CThostFtdcTraderApi_ReqUserLogin(
1194 self.api_ptr,
1195 req as *const _ as *const c_void,
1196 request_id,
1197 )
1198 };
1199
1200 if result != 0 {
1201 return Err(CtpError::FfiError(format!("登录请求失败: {}", result)));
1202 }
1203
1204 Ok(request_id)
1205 }
1206
1207 pub fn req_user_logout(&mut self) -> CtpResult<i32> {
1209 if self.api_ptr.is_null() {
1210 return Err(CtpError::InitializationError("API未初始化".to_string()));
1211 }
1212
1213 let request_id = self.next_request_id();
1214
1215 let result =
1216 unsafe { CThostFtdcTraderApi_ReqUserLogout(self.api_ptr, ptr::null(), request_id) };
1217
1218 if result != 0 {
1219 return Err(CtpError::FfiError(format!("登出请求失败: {}", result)));
1220 }
1221
1222 Ok(request_id)
1223 }
1224
1225 pub fn req_qry_trading_account(&mut self, req: &QryTradingAccountField) -> CtpResult<i32> {
1227 if self.api_ptr.is_null() {
1228 return Err(CtpError::InitializationError("API未初始化".to_string()));
1229 }
1230
1231 let request_id = self.next_request_id();
1232
1233 let result = unsafe {
1234 CThostFtdcTraderApi_ReqQryTradingAccount(
1235 self.api_ptr,
1236 req as *const _ as *const c_void,
1237 request_id,
1238 )
1239 };
1240
1241 if result != 0 {
1242 return Err(CtpError::FfiError(format!(
1243 "查询资金账户请求失败: {}",
1244 result
1245 )));
1246 }
1247
1248 Ok(request_id)
1249 }
1250
1251 pub fn req_qry_investor_position(&mut self, req: &QryInvestorPositionField) -> CtpResult<i32> {
1253 if self.api_ptr.is_null() {
1254 return Err(CtpError::InitializationError("API未初始化".to_string()));
1255 }
1256
1257 let request_id = self.next_request_id();
1258
1259 let result = unsafe {
1260 CThostFtdcTraderApi_ReqQryInvestorPosition(
1261 self.api_ptr,
1262 req as *const _ as *const c_void,
1263 request_id,
1264 )
1265 };
1266
1267 if result != 0 {
1268 return Err(CtpError::FfiError(format!(
1269 "查询投资者持仓请求失败: {}",
1270 result
1271 )));
1272 }
1273
1274 Ok(request_id)
1275 }
1276
1277 pub fn req_order_insert(&mut self, req: &InputOrderField) -> CtpResult<i32> {
1281 if self.api_ptr.is_null() {
1282 return Err(CtpError::InitializationError("API未初始化".to_string()));
1283 }
1284
1285 let request_id = self.next_request_id();
1286
1287 let result = unsafe {
1288 CThostFtdcTraderApi_ReqOrderInsert(
1289 self.api_ptr,
1290 req as *const _ as *const c_void,
1291 request_id,
1292 )
1293 };
1294
1295 if result != 0 {
1296 return Err(CtpError::FfiError(format!("报单录入请求失败: {}", result)));
1297 }
1298
1299 Ok(request_id)
1300 }
1301
1302 pub fn req_order_action(&mut self, req: &InputOrderActionField) -> CtpResult<i32> {
1304 if self.api_ptr.is_null() {
1305 return Err(CtpError::InitializationError("API未初始化".to_string()));
1306 }
1307
1308 let request_id = self.next_request_id();
1309
1310 let result = unsafe {
1311 CThostFtdcTraderApi_ReqOrderAction(
1312 self.api_ptr,
1313 req as *const _ as *const c_void,
1314 request_id,
1315 )
1316 };
1317
1318 if result != 0 {
1319 return Err(CtpError::FfiError(format!("报单操作请求失败: {}", result)));
1320 }
1321
1322 Ok(request_id)
1323 }
1324
1325 pub fn req_qry_order(&mut self, req: &QryOrderField) -> CtpResult<i32> {
1327 if self.api_ptr.is_null() {
1328 return Err(CtpError::InitializationError("API未初始化".to_string()));
1329 }
1330
1331 let request_id = self.next_request_id();
1332
1333 let result = unsafe {
1334 CThostFtdcTraderApi_ReqQryOrder(
1335 self.api_ptr,
1336 req as *const _ as *const c_void,
1337 request_id,
1338 )
1339 };
1340
1341 if result != 0 {
1342 return Err(CtpError::FfiError(format!("查询报单请求失败: {}", result)));
1343 }
1344
1345 Ok(request_id)
1346 }
1347
1348 pub fn req_qry_trade(&mut self, req: &QryTradeField) -> CtpResult<i32> {
1350 if self.api_ptr.is_null() {
1351 return Err(CtpError::InitializationError("API未初始化".to_string()));
1352 }
1353
1354 let request_id = self.next_request_id();
1355
1356 let result = unsafe {
1357 CThostFtdcTraderApi_ReqQryTrade(
1358 self.api_ptr,
1359 req as *const _ as *const c_void,
1360 request_id,
1361 )
1362 };
1363
1364 if result != 0 {
1365 return Err(CtpError::FfiError(format!("查询成交请求失败: {}", result)));
1366 }
1367
1368 Ok(request_id)
1369 }
1370
1371 pub fn req_qry_instrument(&mut self, req: &QryInstrumentField) -> CtpResult<i32> {
1373 if self.api_ptr.is_null() {
1374 return Err(CtpError::InitializationError("API未初始化".to_string()));
1375 }
1376
1377 let request_id = self.next_request_id();
1378
1379 let result = unsafe {
1380 CThostFtdcTraderApi_ReqQryInstrument(
1381 self.api_ptr,
1382 req as *const _ as *const c_void,
1383 request_id,
1384 )
1385 };
1386
1387 if result != 0 {
1388 return Err(CtpError::FfiError(format!("查询合约请求失败: {}", result)));
1389 }
1390
1391 Ok(request_id)
1392 }
1393
1394 pub fn req_qry_instrument_margin_rate(
1398 &mut self,
1399 req: &QryInstrumentMarginRateField,
1400 ) -> CtpResult<i32> {
1401 if self.api_ptr.is_null() {
1402 return Err(CtpError::InitializationError("API未初始化".to_string()));
1403 }
1404
1405 let request_id = self.next_request_id();
1406
1407 let result = unsafe {
1408 CThostFtdcTraderApi_ReqQryInstrumentMarginRate(
1409 self.api_ptr,
1410 req as *const _ as *const c_void,
1411 request_id,
1412 )
1413 };
1414
1415 if result != 0 {
1416 return Err(CtpError::FfiError(format!(
1417 "查询合约保证金率请求失败: {}",
1418 result
1419 )));
1420 }
1421
1422 Ok(request_id)
1423 }
1424
1425 pub fn req_qry_instrument_commission_rate(
1427 &mut self,
1428 req: &QryInstrumentCommissionRateField,
1429 ) -> CtpResult<i32> {
1430 if self.api_ptr.is_null() {
1431 return Err(CtpError::InitializationError("API未初始化".to_string()));
1432 }
1433
1434 let request_id = self.next_request_id();
1435
1436 let result = unsafe {
1437 CThostFtdcTraderApi_ReqQryInstrumentCommissionRate(
1438 self.api_ptr,
1439 req as *const _ as *const c_void,
1440 request_id,
1441 )
1442 };
1443
1444 if result != 0 {
1445 return Err(CtpError::FfiError(format!(
1446 "查询合约手续费率请求失败: {}",
1447 result
1448 )));
1449 }
1450
1451 Ok(request_id)
1452 }
1453
1454 pub fn req_qry_exchange(&mut self, req: &QryExchangeField) -> CtpResult<i32> {
1456 if self.api_ptr.is_null() {
1457 return Err(CtpError::InitializationError("API未初始化".to_string()));
1458 }
1459
1460 let request_id = self.next_request_id();
1461
1462 let result = unsafe {
1463 CThostFtdcTraderApi_ReqQryExchange(
1464 self.api_ptr,
1465 req as *const _ as *const c_void,
1466 request_id,
1467 )
1468 };
1469
1470 if result != 0 {
1471 return Err(CtpError::FfiError(format!(
1472 "查询交易所请求失败: {}",
1473 result
1474 )));
1475 }
1476
1477 Ok(request_id)
1478 }
1479
1480 pub fn req_qry_product(&mut self, req: &QryProductField) -> CtpResult<i32> {
1482 if self.api_ptr.is_null() {
1483 return Err(CtpError::InitializationError("API未初始化".to_string()));
1484 }
1485
1486 let request_id = self.next_request_id();
1487
1488 let result = unsafe {
1489 CThostFtdcTraderApi_ReqQryProduct(
1490 self.api_ptr,
1491 req as *const _ as *const c_void,
1492 request_id,
1493 )
1494 };
1495
1496 if result != 0 {
1497 return Err(CtpError::FfiError(format!("查询产品请求失败: {}", result)));
1498 }
1499
1500 Ok(request_id)
1501 }
1502
1503 pub fn req_settlement_info_confirm(
1505 &mut self,
1506 req: &SettlementInfoConfirmField,
1507 ) -> CtpResult<i32> {
1508 if self.api_ptr.is_null() {
1509 return Err(CtpError::InitializationError("API未初始化".to_string()));
1510 }
1511
1512 let request_id = self.next_request_id();
1513
1514 let result = unsafe {
1515 CThostFtdcTraderApi_ReqSettlementInfoConfirm(
1516 self.api_ptr,
1517 req as *const _ as *const c_void,
1518 request_id,
1519 )
1520 };
1521
1522 if result != 0 {
1523 return Err(CtpError::FfiError(format!(
1524 "投资者结算结果确认请求失败: {}",
1525 result
1526 )));
1527 }
1528
1529 Ok(request_id)
1530 }
1531
1532 pub fn req_parked_order_insert(&mut self, req: &ParkedOrderField) -> CtpResult<i32> {
1534 if self.api_ptr.is_null() {
1535 return Err(CtpError::InitializationError("API未初始化".to_string()));
1536 }
1537
1538 let request_id = self.next_request_id();
1539
1540 let result = unsafe {
1541 CThostFtdcTraderApi_ReqParkedOrderInsert(
1542 self.api_ptr,
1543 req as *const _ as *const c_void,
1544 request_id,
1545 )
1546 };
1547
1548 if result != 0 {
1549 return Err(CtpError::FfiError(format!(
1550 "预埋单录入请求失败: {}",
1551 result
1552 )));
1553 }
1554
1555 Ok(request_id)
1556 }
1557
1558 pub fn req_parked_order_action(&mut self, req: &ParkedOrderActionField) -> CtpResult<i32> {
1560 if self.api_ptr.is_null() {
1561 return Err(CtpError::InitializationError("API未初始化".to_string()));
1562 }
1563
1564 let request_id = self.next_request_id();
1565
1566 let result = unsafe {
1567 CThostFtdcTraderApi_ReqParkedOrderAction(
1568 self.api_ptr,
1569 req as *const _ as *const c_void,
1570 request_id,
1571 )
1572 };
1573
1574 if result != 0 {
1575 return Err(CtpError::FfiError(format!(
1576 "预埋撤单录入请求失败: {}",
1577 result
1578 )));
1579 }
1580
1581 Ok(request_id)
1582 }
1583
1584 pub fn req_exec_order_insert(&mut self, req: &InputExecOrderField) -> CtpResult<i32> {
1588 if self.api_ptr.is_null() {
1589 return Err(CtpError::InitializationError("API未初始化".to_string()));
1590 }
1591
1592 let request_id = self.next_request_id();
1593
1594 let result = unsafe {
1595 CThostFtdcTraderApi_ReqExecOrderInsert(
1596 self.api_ptr,
1597 req as *const _ as *const c_void,
1598 request_id,
1599 )
1600 };
1601
1602 if result != 0 {
1603 return Err(CtpError::FfiError(format!(
1604 "执行宣告录入请求失败: {}",
1605 result
1606 )));
1607 }
1608
1609 Ok(request_id)
1610 }
1611
1612 pub fn req_exec_order_action(&mut self, req: &InputExecOrderActionField) -> CtpResult<i32> {
1614 if self.api_ptr.is_null() {
1615 return Err(CtpError::InitializationError("API未初始化".to_string()));
1616 }
1617
1618 let request_id = self.next_request_id();
1619
1620 let result = unsafe {
1621 CThostFtdcTraderApi_ReqExecOrderAction(
1622 self.api_ptr,
1623 req as *const _ as *const c_void,
1624 request_id,
1625 )
1626 };
1627
1628 if result != 0 {
1629 return Err(CtpError::FfiError(format!(
1630 "执行宣告操作请求失败: {}",
1631 result
1632 )));
1633 }
1634
1635 Ok(request_id)
1636 }
1637
1638 pub fn req_for_quote_insert(&mut self, req: &InputForQuoteField) -> CtpResult<i32> {
1640 if self.api_ptr.is_null() {
1641 return Err(CtpError::InitializationError("API未初始化".to_string()));
1642 }
1643
1644 let request_id = self.next_request_id();
1645
1646 let result = unsafe {
1647 CThostFtdcTraderApi_ReqForQuoteInsert(
1648 self.api_ptr,
1649 req as *const _ as *const c_void,
1650 request_id,
1651 )
1652 };
1653
1654 if result != 0 {
1655 return Err(CtpError::FfiError(format!("询价录入请求失败: {}", result)));
1656 }
1657
1658 Ok(request_id)
1659 }
1660
1661 pub fn req_quote_insert(&mut self, req: &InputQuoteField) -> CtpResult<i32> {
1663 if self.api_ptr.is_null() {
1664 return Err(CtpError::InitializationError("API未初始化".to_string()));
1665 }
1666
1667 let request_id = self.next_request_id();
1668
1669 let result = unsafe {
1670 CThostFtdcTraderApi_ReqQuoteInsert(
1671 self.api_ptr,
1672 req as *const _ as *const c_void,
1673 request_id,
1674 )
1675 };
1676
1677 if result != 0 {
1678 return Err(CtpError::FfiError(format!("报价录入请求失败: {}", result)));
1679 }
1680
1681 Ok(request_id)
1682 }
1683
1684 pub fn req_quote_action(&mut self, req: &InputQuoteActionField) -> CtpResult<i32> {
1686 if self.api_ptr.is_null() {
1687 return Err(CtpError::InitializationError("API未初始化".to_string()));
1688 }
1689
1690 let request_id = self.next_request_id();
1691
1692 let result = unsafe {
1693 CThostFtdcTraderApi_ReqQuoteAction(
1694 self.api_ptr,
1695 req as *const _ as *const c_void,
1696 request_id,
1697 )
1698 };
1699
1700 if result != 0 {
1701 return Err(CtpError::FfiError(format!("报价操作请求失败: {}", result)));
1702 }
1703
1704 Ok(request_id)
1705 }
1706
1707 pub fn req_batch_order_action(&mut self, req: &InputBatchOrderActionField) -> CtpResult<i32> {
1709 if self.api_ptr.is_null() {
1710 return Err(CtpError::InitializationError("API未初始化".to_string()));
1711 }
1712
1713 let request_id = self.next_request_id();
1714
1715 let result = unsafe {
1716 CThostFtdcTraderApi_ReqBatchOrderAction(
1717 self.api_ptr,
1718 req as *const _ as *const c_void,
1719 request_id,
1720 )
1721 };
1722
1723 if result != 0 {
1724 return Err(CtpError::FfiError(format!(
1725 "批量报单操作请求失败: {}",
1726 result
1727 )));
1728 }
1729
1730 Ok(request_id)
1731 }
1732
1733 pub fn req_remove_parked_order(&mut self, req: &RemoveParkedOrderField) -> CtpResult<i32> {
1735 if self.api_ptr.is_null() {
1736 return Err(CtpError::InitializationError("API未初始化".to_string()));
1737 }
1738
1739 let request_id = self.next_request_id();
1740
1741 let result = unsafe {
1742 CThostFtdcTraderApi_ReqRemoveParkedOrder(
1743 self.api_ptr,
1744 req as *const _ as *const c_void,
1745 request_id,
1746 )
1747 };
1748
1749 if result != 0 {
1750 return Err(CtpError::FfiError(format!(
1751 "删除预埋单请求失败: {}",
1752 result
1753 )));
1754 }
1755
1756 Ok(request_id)
1757 }
1758
1759 pub fn req_remove_parked_order_action(
1761 &mut self,
1762 req: &RemoveParkedOrderActionField,
1763 ) -> CtpResult<i32> {
1764 if self.api_ptr.is_null() {
1765 return Err(CtpError::InitializationError("API未初始化".to_string()));
1766 }
1767
1768 let request_id = self.next_request_id();
1769
1770 let result = unsafe {
1771 CThostFtdcTraderApi_ReqRemoveParkedOrderAction(
1772 self.api_ptr,
1773 req as *const _ as *const c_void,
1774 request_id,
1775 )
1776 };
1777
1778 if result != 0 {
1779 return Err(CtpError::FfiError(format!(
1780 "删除预埋撤单请求失败: {}",
1781 result
1782 )));
1783 }
1784
1785 Ok(request_id)
1786 }
1787
1788 pub fn req_qry_max_order_volume(&mut self, req: &QryMaxOrderVolumeField) -> CtpResult<i32> {
1790 if self.api_ptr.is_null() {
1791 return Err(CtpError::InitializationError("API未初始化".to_string()));
1792 }
1793
1794 let request_id = self.next_request_id();
1795
1796 let result = unsafe {
1797 CThostFtdcTraderApi_ReqQryMaxOrderVolume(
1798 self.api_ptr,
1799 req as *const _ as *const c_void,
1800 request_id,
1801 )
1802 };
1803
1804 if result != 0 {
1805 return Err(CtpError::FfiError(format!(
1806 "查询最大报单数量请求失败: {}",
1807 result
1808 )));
1809 }
1810
1811 Ok(request_id)
1812 }
1813
1814 pub fn req_qry_depth_market_data(&mut self, req: &QryDepthMarketDataField) -> CtpResult<i32> {
1816 if self.api_ptr.is_null() {
1817 return Err(CtpError::InitializationError("API未初始化".to_string()));
1818 }
1819
1820 let request_id = self.next_request_id();
1821
1822 let result = unsafe {
1823 CThostFtdcTraderApi_ReqQryDepthMarketData(
1824 self.api_ptr,
1825 req as *const _ as *const c_void,
1826 request_id,
1827 )
1828 };
1829
1830 if result != 0 {
1831 return Err(CtpError::FfiError(format!("查询行情请求失败: {}", result)));
1832 }
1833
1834 Ok(request_id)
1835 }
1836
1837 pub fn req_qry_settlement_info(&mut self, req: &QrySettlementInfoField) -> CtpResult<i32> {
1839 if self.api_ptr.is_null() {
1840 return Err(CtpError::InitializationError("API未初始化".to_string()));
1841 }
1842
1843 let request_id = self.next_request_id();
1844
1845 let result = unsafe {
1846 CThostFtdcTraderApi_ReqQrySettlementInfo(
1847 self.api_ptr,
1848 req as *const _ as *const c_void,
1849 request_id,
1850 )
1851 };
1852
1853 if result != 0 {
1854 return Err(CtpError::FfiError(format!(
1855 "查询投资者结算结果请求失败: {}",
1856 result
1857 )));
1858 }
1859
1860 Ok(request_id)
1861 }
1862
1863 pub fn req_qry_transfer_bank(&mut self, req: &QryTransferBankField) -> CtpResult<i32> {
1865 if self.api_ptr.is_null() {
1866 return Err(CtpError::InitializationError("API未初始化".to_string()));
1867 }
1868
1869 let request_id = self.next_request_id();
1870
1871 let result = unsafe {
1872 CThostFtdcTraderApi_ReqQryTransferBank(
1873 self.api_ptr,
1874 req as *const _ as *const c_void,
1875 request_id,
1876 )
1877 };
1878
1879 if result != 0 {
1880 return Err(CtpError::FfiError(format!(
1881 "查询转帐银行请求失败: {}",
1882 result
1883 )));
1884 }
1885
1886 Ok(request_id)
1887 }
1888
1889 pub fn req_qry_investor_position_detail(
1891 &mut self,
1892 req: &QryInvestorPositionDetailField,
1893 ) -> CtpResult<i32> {
1894 if self.api_ptr.is_null() {
1895 return Err(CtpError::InitializationError("API未初始化".to_string()));
1896 }
1897
1898 let request_id = self.next_request_id();
1899
1900 let result = unsafe {
1901 CThostFtdcTraderApi_ReqQryInvestorPositionDetail(
1902 self.api_ptr,
1903 req as *const _ as *const c_void,
1904 request_id,
1905 )
1906 };
1907
1908 if result != 0 {
1909 return Err(CtpError::FfiError(format!(
1910 "查询投资者持仓明细请求失败: {}",
1911 result
1912 )));
1913 }
1914
1915 Ok(request_id)
1916 }
1917
1918 pub fn req_qry_notice(&mut self, req: &QryNoticeField) -> CtpResult<i32> {
1920 if self.api_ptr.is_null() {
1921 return Err(CtpError::InitializationError("API未初始化".to_string()));
1922 }
1923
1924 let request_id = self.next_request_id();
1925
1926 let result = unsafe {
1927 CThostFtdcTraderApi_ReqQryNotice(
1928 self.api_ptr,
1929 req as *const _ as *const c_void,
1930 request_id,
1931 )
1932 };
1933
1934 if result != 0 {
1935 return Err(CtpError::FfiError(format!(
1936 "查询客户通知请求失败: {}",
1937 result
1938 )));
1939 }
1940
1941 Ok(request_id)
1942 }
1943
1944 fn next_request_id(&self) -> i32 {
1946 let mut id = self.request_id.lock().unwrap();
1947 let current = *id;
1948 *id += 1;
1949 current
1950 }
1951}
1952
1953#[repr(C)]
1955#[derive(Debug, Clone)]
1956pub struct ReqAuthenticateField {
1957 pub broker_id: [u8; 11],
1959 pub user_id: [u8; 16],
1961 pub user_product_info: [u8; 11],
1963 pub auth_code: [u8; 17],
1965 pub app_id: [u8; 33],
1967}
1968
1969impl Default for ReqAuthenticateField {
1970 fn default() -> Self {
1971 unsafe { std::mem::zeroed() }
1972 }
1973}
1974
1975impl CtpApi for TraderApi {
1976 fn get_version() -> CtpResult<String> {
1977 let version_ptr = unsafe { CThostFtdcTraderApi_GetApiVersion() };
1978 safe_cstr_to_string(version_ptr)
1979 }
1980
1981 fn init(&mut self) -> CtpResult<()> {
1982 if self.api_ptr.is_null() {
1983 return Err(CtpError::InitializationError("API指针为空".to_string()));
1984 }
1985
1986 unsafe {
1987 CThostFtdcTraderApi_Init(self.api_ptr);
1988 }
1989
1990 self.initialized = true;
1991 Ok(())
1992 }
1993
1994 fn release(&mut self) {
1995 if !self.api_ptr.is_null() {
1996 unsafe {
1997 CThostFtdcTraderApi_Release(self.api_ptr);
1998 }
1999 self.api_ptr = ptr::null_mut();
2000 }
2001 self.initialized = false;
2002 }
2003
2004 fn get_trading_day(&self) -> CtpResult<String> {
2005 if self.api_ptr.is_null() {
2006 return Err(CtpError::InitializationError("API未初始化".to_string()));
2007 }
2008
2009 let trading_day_ptr = unsafe { CThostFtdcTraderApi_GetTradingDay(self.api_ptr) };
2010
2011 safe_cstr_to_string(trading_day_ptr)
2012 }
2013
2014 fn register_front(&mut self, front_address: &str) -> CtpResult<()> {
2015 if self.api_ptr.is_null() {
2016 return Err(CtpError::InitializationError("API未初始化".to_string()));
2017 }
2018 let front_address_cstr = to_cstring(front_address)?;
2019 unsafe {
2020 CThostFtdcTraderApi_RegisterFront(self.api_ptr, front_address_cstr.as_ptr());
2021 }
2022
2023 Ok(())
2024 }
2025
2026 fn join(&self) -> CtpResult<i32> {
2027 if self.api_ptr.is_null() {
2028 return Err(CtpError::InitializationError("API未初始化".to_string()));
2029 }
2030
2031 let result = unsafe { CThostFtdcTraderApi_Join(self.api_ptr) };
2032
2033 Ok(result)
2034 }
2035}
2036
2037extern "C" fn on_front_connected_callback(user_data: *mut c_void) {
2039 unsafe {
2040 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2041 if let Some(ref mut handler) = api.handler {
2042 handler.on_front_connected();
2043 }
2044 }
2045 }
2046}
2047
2048extern "C" fn on_front_disconnected_callback(user_data: *mut c_void, reason: c_int) {
2049 unsafe {
2050 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2051 if let Some(ref mut handler) = api.handler {
2052 handler.on_front_disconnected(reason);
2053 }
2054 }
2055 }
2056}
2057
2058extern "C" fn on_heart_beat_warning_callback(user_data: *mut c_void, time_lapse: c_int) {
2059 unsafe {
2060 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2061 if let Some(ref mut handler) = api.handler {
2062 handler.on_heart_beat_warning(time_lapse);
2063 }
2064 }
2065 }
2066}
2067
2068extern "C" fn on_rsp_authenticate_callback(
2069 user_data: *mut c_void,
2070 rsp_authenticate: *mut c_void,
2071 rsp_info: *mut c_void,
2072 request_id: c_int,
2073 is_last: c_int,
2074) {
2075 unsafe {
2076 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2077 if let Some(ref mut handler) = api.handler {
2078 let parsed_rsp_authenticate = if !rsp_authenticate.is_null() {
2080 let auth_ptr = rsp_authenticate as *const RspAuthenticateField;
2081 Some((*auth_ptr).clone())
2082 } else {
2083 None
2084 };
2085
2086 let parsed_rsp_info = if !rsp_info.is_null() {
2088 let rsp_ptr = rsp_info as *const RspInfoField;
2089 Some((*rsp_ptr).clone())
2090 } else {
2091 None
2092 };
2093
2094 handler.on_rsp_authenticate(
2095 parsed_rsp_authenticate,
2096 parsed_rsp_info,
2097 request_id,
2098 is_last != 0,
2099 );
2100 }
2101 }
2102 }
2103}
2104
2105extern "C" fn on_rsp_user_login_callback(
2106 user_data: *mut c_void,
2107 user_login: *mut c_void,
2108 rsp_info: *mut c_void,
2109 request_id: c_int,
2110 is_last: c_int,
2111) {
2112 unsafe {
2113 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2114 if let Some(ref mut handler) = api.handler {
2115 let parsed_user_login = if !user_login.is_null() {
2117 let login_ptr = user_login as *const RspUserLoginField;
2118 Some((*login_ptr).clone())
2119 } else {
2120 None
2121 };
2122
2123 let parsed_rsp_info = if !rsp_info.is_null() {
2125 let rsp_ptr = rsp_info as *const RspInfoField;
2126 Some((*rsp_ptr).clone())
2127 } else {
2128 None
2129 };
2130
2131 handler.on_rsp_user_login(
2132 parsed_user_login,
2133 parsed_rsp_info,
2134 request_id,
2135 is_last != 0,
2136 );
2137 }
2138 }
2139 }
2140}
2141
2142extern "C" fn on_rsp_user_logout_callback(
2143 user_data: *mut c_void,
2144 _user_logout: *mut c_void,
2145 rsp_info: *mut c_void,
2146 request_id: c_int,
2147 is_last: c_int,
2148) {
2149 unsafe {
2150 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2151 if let Some(ref mut handler) = api.handler {
2152 let parsed_rsp_info = if !rsp_info.is_null() {
2154 let rsp_ptr = rsp_info as *const RspInfoField;
2155 Some((*rsp_ptr).clone())
2156 } else {
2157 None
2158 };
2159
2160 handler.on_rsp_user_logout(None, parsed_rsp_info, request_id, is_last != 0);
2161 }
2162 }
2163 }
2164}
2165
2166extern "C" fn on_rsp_error_callback(
2167 user_data: *mut c_void,
2168 rsp_info: *mut c_void,
2169 request_id: c_int,
2170 is_last: c_int,
2171) {
2172 unsafe {
2173 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2174 if let Some(ref mut handler) = api.handler {
2175 let parsed_rsp_info = if !rsp_info.is_null() {
2177 let rsp_ptr = rsp_info as *const RspInfoField;
2178 Some((*rsp_ptr).clone())
2179 } else {
2180 None
2181 };
2182
2183 handler.on_rsp_error(parsed_rsp_info, request_id, is_last != 0);
2184 }
2185 }
2186 }
2187}
2188
2189extern "C" fn on_rsp_order_insert_callback(
2190 user_data: *mut c_void,
2191 input_order: *mut c_void,
2192 rsp_info: *mut c_void,
2193 request_id: c_int,
2194 is_last: c_int,
2195) {
2196 unsafe {
2197 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2198 if let Some(ref mut handler) = api.handler {
2199 let parsed_input_order = if !input_order.is_null() {
2201 let order_ptr = input_order as *const InputOrderField;
2202 Some((*order_ptr).clone())
2203 } else {
2204 None
2205 };
2206
2207 let parsed_rsp_info = if !rsp_info.is_null() {
2209 let rsp_ptr = rsp_info as *const RspInfoField;
2210 Some((*rsp_ptr).clone())
2211 } else {
2212 None
2213 };
2214
2215 handler.on_rsp_order_insert(
2216 parsed_input_order,
2217 parsed_rsp_info,
2218 request_id,
2219 is_last != 0,
2220 );
2221 }
2222 }
2223 }
2224}
2225
2226extern "C" fn on_rsp_order_action_callback(
2227 user_data: *mut c_void,
2228 input_order_action: *mut c_void,
2229 rsp_info: *mut c_void,
2230 request_id: c_int,
2231 is_last: c_int,
2232) {
2233 unsafe {
2234 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2235 if let Some(ref mut handler) = api.handler {
2236 let parsed_input_order_action = if !input_order_action.is_null() {
2238 let action_ptr = input_order_action as *const InputOrderActionField;
2239 Some((*action_ptr).clone())
2240 } else {
2241 None
2242 };
2243
2244 let parsed_rsp_info = if !rsp_info.is_null() {
2246 let rsp_ptr = rsp_info as *const RspInfoField;
2247 Some((*rsp_ptr).clone())
2248 } else {
2249 None
2250 };
2251
2252 handler.on_rsp_order_action(
2253 parsed_input_order_action,
2254 parsed_rsp_info,
2255 request_id,
2256 is_last != 0,
2257 );
2258 }
2259 }
2260 }
2261}
2262
2263extern "C" fn on_rtn_order_callback(user_data: *mut c_void, order: *mut c_void) {
2264 unsafe {
2265 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2266 if let Some(ref mut handler) = api.handler {
2267 if !order.is_null() {
2269 let order_ptr = order as *const OrderField;
2270 let parsed_order = (*order_ptr).clone();
2271 handler.on_rtn_order(parsed_order);
2272 } else {
2273 let temp_order = OrderField::default();
2275 handler.on_rtn_order(temp_order);
2276 }
2277 }
2278 }
2279 }
2280}
2281
2282extern "C" fn on_rtn_trade_callback(user_data: *mut c_void, trade: *mut c_void) {
2283 unsafe {
2284 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2285 if let Some(ref mut handler) = api.handler {
2286 if !trade.is_null() {
2288 let trade_ptr = trade as *const TradeField;
2289 let parsed_trade = (*trade_ptr).clone();
2290 handler.on_rtn_trade(parsed_trade);
2291 } else {
2292 let temp_trade = TradeField::default();
2294 handler.on_rtn_trade(temp_trade);
2295 }
2296 }
2297 }
2298 }
2299}
2300
2301extern "C" fn on_rsp_qry_trading_account_callback(
2302 user_data: *mut c_void,
2303 trading_account: *mut c_void,
2304 rsp_info: *mut c_void,
2305 request_id: c_int,
2306 is_last: c_int,
2307) {
2308 unsafe {
2309 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2312 if let Some(ref mut handler) = api.handler {
2313 let parsed_trading_account = if !trading_account.is_null() {
2314 let account_ptr = trading_account as *const TradingAccountField;
2315 Some((*account_ptr).clone())
2316 } else {
2317 None
2318 };
2319
2320 let parsed_rsp_info = if !rsp_info.is_null() {
2321 let info_ptr = rsp_info as *const RspInfoField;
2322 Some((*info_ptr).clone())
2323 } else {
2324 None
2325 };
2326
2327 handler.on_rsp_qry_trading_account(
2328 parsed_trading_account,
2329 parsed_rsp_info,
2330 request_id,
2331 is_last != 0,
2332 );
2333 }
2334 }
2335 }
2336}
2337
2338extern "C" fn on_rsp_qry_investor_position_callback(
2339 user_data: *mut c_void,
2340 investor_position: *mut c_void,
2341 rsp_info: *mut c_void,
2342 request_id: c_int,
2343 is_last: c_int,
2344) {
2345 unsafe {
2346 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2347 if let Some(ref mut handler) = api.handler {
2348 let parsed_investor_position = if !investor_position.is_null() {
2349 let position_ptr = investor_position as *const InvestorPositionField;
2350 Some((*position_ptr).clone())
2351 } else {
2352 None
2353 };
2354
2355 let parsed_rsp_info = if !rsp_info.is_null() {
2356 let info_ptr = rsp_info as *const RspInfoField;
2357 Some((*info_ptr).clone())
2358 } else {
2359 None
2360 };
2361
2362 handler.on_rsp_qry_investor_position(
2363 parsed_investor_position,
2364 parsed_rsp_info,
2365 request_id,
2366 is_last != 0,
2367 );
2368 }
2369 }
2370 }
2371}
2372
2373extern "C" fn on_err_rtn_order_insert_callback(
2376 user_data: *mut c_void,
2377 input_order: *mut c_void,
2378 rsp_info: *mut c_void,
2379) {
2380 unsafe {
2381 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2382 if let Some(ref mut handler) = api.handler {
2383 let parsed_input_order = if !input_order.is_null() {
2384 let order_ptr = input_order as *const InputOrderField;
2385 Some((*order_ptr).clone())
2386 } else {
2387 None
2388 };
2389
2390 let parsed_rsp_info = if !rsp_info.is_null() {
2391 let info_ptr = rsp_info as *const RspInfoField;
2392 Some((*info_ptr).clone())
2393 } else {
2394 None
2395 };
2396
2397 handler.on_err_rtn_order_insert(parsed_input_order, parsed_rsp_info);
2398 }
2399 }
2400 }
2401}
2402
2403extern "C" fn on_err_rtn_order_action_callback(
2404 user_data: *mut c_void,
2405 order_action: *mut c_void,
2406 rsp_info: *mut c_void,
2407) {
2408 unsafe {
2409 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2410 if let Some(ref mut handler) = api.handler {
2411 let parsed_order_action = if !order_action.is_null() {
2412 let action_ptr = order_action as *const OrderActionField;
2413 Some((*action_ptr).clone())
2414 } else {
2415 None
2416 };
2417
2418 let parsed_rsp_info = if !rsp_info.is_null() {
2419 let info_ptr = rsp_info as *const RspInfoField;
2420 Some((*info_ptr).clone())
2421 } else {
2422 None
2423 };
2424
2425 handler.on_err_rtn_order_action(parsed_order_action, parsed_rsp_info);
2426 }
2427 }
2428 }
2429}
2430
2431extern "C" fn on_rsp_qry_order_callback(
2432 user_data: *mut c_void,
2433 order: *mut c_void,
2434 rsp_info: *mut c_void,
2435 request_id: c_int,
2436 is_last: c_int,
2437) {
2438 unsafe {
2439 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2440 if let Some(ref mut handler) = api.handler {
2441 let parsed_order = if !order.is_null() {
2442 let order_ptr = order as *const OrderField;
2443 Some((*order_ptr).clone())
2444 } else {
2445 None
2446 };
2447
2448 let parsed_rsp_info = if !rsp_info.is_null() {
2449 let info_ptr = rsp_info as *const RspInfoField;
2450 Some((*info_ptr).clone())
2451 } else {
2452 None
2453 };
2454
2455 handler.on_rsp_qry_order(parsed_order, parsed_rsp_info, request_id, is_last != 0);
2456 }
2457 }
2458 }
2459}
2460
2461extern "C" fn on_rsp_qry_trade_callback(
2462 user_data: *mut c_void,
2463 trade: *mut c_void,
2464 rsp_info: *mut c_void,
2465 request_id: c_int,
2466 is_last: c_int,
2467) {
2468 unsafe {
2469 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2470 if let Some(ref mut handler) = api.handler {
2471 let parsed_trade = if !trade.is_null() {
2472 let trade_ptr = trade as *const TradeField;
2473 Some((*trade_ptr).clone())
2474 } else {
2475 None
2476 };
2477
2478 let parsed_rsp_info = if !rsp_info.is_null() {
2479 let info_ptr = rsp_info as *const RspInfoField;
2480 Some((*info_ptr).clone())
2481 } else {
2482 None
2483 };
2484
2485 handler.on_rsp_qry_trade(parsed_trade, parsed_rsp_info, request_id, is_last != 0);
2486 }
2487 }
2488 }
2489}
2490
2491extern "C" fn on_rsp_qry_instrument_callback(
2492 user_data: *mut c_void,
2493 instrument: *mut c_void,
2494 rsp_info: *mut c_void,
2495 request_id: c_int,
2496 is_last: c_int,
2497) {
2498 unsafe {
2499 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2500 if let Some(ref mut handler) = api.handler {
2501 let parsed_instrument = if !instrument.is_null() {
2502 let instrument_ptr = instrument as *const InstrumentField;
2503 Some((*instrument_ptr).clone())
2504 } else {
2505 None
2506 };
2507
2508 let parsed_rsp_info = if !rsp_info.is_null() {
2509 let info_ptr = rsp_info as *const RspInfoField;
2510 Some((*info_ptr).clone())
2511 } else {
2512 None
2513 };
2514
2515 handler.on_rsp_qry_instrument(
2516 parsed_instrument,
2517 parsed_rsp_info,
2518 request_id,
2519 is_last != 0,
2520 );
2521 }
2522 }
2523 }
2524}
2525
2526extern "C" fn on_rsp_qry_instrument_margin_rate_callback(
2529 user_data: *mut c_void,
2530 margin_rate: *mut c_void,
2531 rsp_info: *mut c_void,
2532 request_id: c_int,
2533 is_last: c_int,
2534) {
2535 unsafe {
2536 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2537 if let Some(ref mut handler) = api.handler {
2538 let parsed_margin_rate = if !margin_rate.is_null() {
2539 let margin_rate_ptr = margin_rate as *const InstrumentMarginRateField;
2540 Some((*margin_rate_ptr).clone())
2541 } else {
2542 None
2543 };
2544
2545 let parsed_rsp_info = if !rsp_info.is_null() {
2546 let info_ptr = rsp_info as *const RspInfoField;
2547 Some((*info_ptr).clone())
2548 } else {
2549 None
2550 };
2551
2552 handler.on_rsp_qry_instrument_margin_rate(
2553 parsed_margin_rate,
2554 parsed_rsp_info,
2555 request_id,
2556 is_last != 0,
2557 );
2558 }
2559 }
2560 }
2561}
2562
2563extern "C" fn on_rsp_qry_instrument_commission_rate_callback(
2564 user_data: *mut c_void,
2565 commission_rate: *mut c_void,
2566 rsp_info: *mut c_void,
2567 request_id: c_int,
2568 is_last: c_int,
2569) {
2570 unsafe {
2571 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2572 if let Some(ref mut handler) = api.handler {
2573 let parsed_commission_rate = if !commission_rate.is_null() {
2574 let commission_rate_ptr =
2575 commission_rate as *const InstrumentCommissionRateField;
2576 Some((*commission_rate_ptr).clone())
2577 } else {
2578 None
2579 };
2580
2581 let parsed_rsp_info = if !rsp_info.is_null() {
2582 let info_ptr = rsp_info as *const RspInfoField;
2583 Some((*info_ptr).clone())
2584 } else {
2585 None
2586 };
2587
2588 handler.on_rsp_qry_instrument_commission_rate(
2589 parsed_commission_rate,
2590 parsed_rsp_info,
2591 request_id,
2592 is_last != 0,
2593 );
2594 }
2595 }
2596 }
2597}
2598
2599extern "C" fn on_rsp_qry_exchange_callback(
2600 user_data: *mut c_void,
2601 exchange: *mut c_void,
2602 rsp_info: *mut c_void,
2603 request_id: c_int,
2604 is_last: c_int,
2605) {
2606 unsafe {
2607 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2608 if let Some(ref mut handler) = api.handler {
2609 let parsed_exchange = if !exchange.is_null() {
2610 let exchange_ptr = exchange as *const ExchangeField;
2611 Some((*exchange_ptr).clone())
2612 } else {
2613 None
2614 };
2615
2616 let parsed_rsp_info = if !rsp_info.is_null() {
2617 let info_ptr = rsp_info as *const RspInfoField;
2618 Some((*info_ptr).clone())
2619 } else {
2620 None
2621 };
2622
2623 handler.on_rsp_qry_exchange(
2624 parsed_exchange,
2625 parsed_rsp_info,
2626 request_id,
2627 is_last != 0,
2628 );
2629 }
2630 }
2631 }
2632}
2633
2634extern "C" fn on_rsp_qry_product_callback(
2635 user_data: *mut c_void,
2636 product: *mut c_void,
2637 rsp_info: *mut c_void,
2638 request_id: c_int,
2639 is_last: c_int,
2640) {
2641 unsafe {
2642 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2643 if let Some(ref mut handler) = api.handler {
2644 let parsed_product = if !product.is_null() {
2645 let product_ptr = product as *const ProductField;
2646 Some((*product_ptr).clone())
2647 } else {
2648 None
2649 };
2650
2651 let parsed_rsp_info = if !rsp_info.is_null() {
2652 let info_ptr = rsp_info as *const RspInfoField;
2653 Some((*info_ptr).clone())
2654 } else {
2655 None
2656 };
2657
2658 handler.on_rsp_qry_product(
2659 parsed_product,
2660 parsed_rsp_info,
2661 request_id,
2662 is_last != 0,
2663 );
2664 }
2665 }
2666 }
2667}
2668
2669extern "C" fn on_rsp_settlement_info_confirm_callback(
2670 user_data: *mut c_void,
2671 settlement_info_confirm: *mut c_void,
2672 rsp_info: *mut c_void,
2673 request_id: c_int,
2674 is_last: c_int,
2675) {
2676 unsafe {
2677 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2678 if let Some(ref mut handler) = api.handler {
2679 let parsed_settlement_info_confirm = if !settlement_info_confirm.is_null() {
2680 let settlement_ptr =
2681 settlement_info_confirm as *const SettlementInfoConfirmField;
2682 Some((*settlement_ptr).clone())
2683 } else {
2684 None
2685 };
2686
2687 let parsed_rsp_info = if !rsp_info.is_null() {
2688 let info_ptr = rsp_info as *const RspInfoField;
2689 Some((*info_ptr).clone())
2690 } else {
2691 None
2692 };
2693
2694 handler.on_rsp_settlement_info_confirm(
2695 parsed_settlement_info_confirm,
2696 parsed_rsp_info,
2697 request_id,
2698 is_last != 0,
2699 );
2700 }
2701 }
2702 }
2703}
2704
2705extern "C" fn on_rsp_parked_order_insert_callback(
2706 user_data: *mut c_void,
2707 parked_order: *mut c_void,
2708 rsp_info: *mut c_void,
2709 request_id: c_int,
2710 is_last: c_int,
2711) {
2712 unsafe {
2713 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2714 if let Some(ref mut handler) = api.handler {
2715 let parsed_parked_order = if !parked_order.is_null() {
2716 let parked_order_ptr = parked_order as *const ParkedOrderField;
2717 Some((*parked_order_ptr).clone())
2718 } else {
2719 None
2720 };
2721
2722 let parsed_rsp_info = if !rsp_info.is_null() {
2723 let info_ptr = rsp_info as *const RspInfoField;
2724 Some((*info_ptr).clone())
2725 } else {
2726 None
2727 };
2728
2729 handler.on_rsp_parked_order_insert(
2730 parsed_parked_order,
2731 parsed_rsp_info,
2732 request_id,
2733 is_last != 0,
2734 );
2735 }
2736 }
2737 }
2738}
2739
2740extern "C" fn on_rsp_parked_order_action_callback(
2741 user_data: *mut c_void,
2742 parked_order_action: *mut c_void,
2743 rsp_info: *mut c_void,
2744 request_id: c_int,
2745 is_last: c_int,
2746) {
2747 unsafe {
2748 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2749 if let Some(ref mut handler) = api.handler {
2750 let parsed_parked_order_action = if !parked_order_action.is_null() {
2751 let parked_action_ptr = parked_order_action as *const ParkedOrderActionField;
2752 Some((*parked_action_ptr).clone())
2753 } else {
2754 None
2755 };
2756
2757 let parsed_rsp_info = if !rsp_info.is_null() {
2758 let info_ptr = rsp_info as *const RspInfoField;
2759 Some((*info_ptr).clone())
2760 } else {
2761 None
2762 };
2763
2764 handler.on_rsp_parked_order_action(
2765 parsed_parked_order_action,
2766 parsed_rsp_info,
2767 request_id,
2768 is_last != 0,
2769 );
2770 }
2771 }
2772 }
2773}
2774
2775extern "C" fn on_rsp_exec_order_insert_callback(
2778 user_data: *mut c_void,
2779 input_exec_order: *mut c_void,
2780 rsp_info: *mut c_void,
2781 request_id: c_int,
2782 is_last: c_int,
2783) {
2784 unsafe {
2785 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2786 if let Some(ref mut handler) = api.handler {
2787 let parsed_input_exec_order = if !input_exec_order.is_null() {
2788 let exec_order_ptr = input_exec_order as *const InputExecOrderField;
2789 Some((*exec_order_ptr).clone())
2790 } else {
2791 None
2792 };
2793
2794 let parsed_rsp_info = if !rsp_info.is_null() {
2795 let info_ptr = rsp_info as *const RspInfoField;
2796 Some((*info_ptr).clone())
2797 } else {
2798 None
2799 };
2800
2801 handler.on_rsp_exec_order_insert(
2802 parsed_input_exec_order,
2803 parsed_rsp_info,
2804 request_id,
2805 is_last != 0,
2806 );
2807 }
2808 }
2809 }
2810}
2811
2812extern "C" fn on_rsp_exec_order_action_callback(
2813 user_data: *mut c_void,
2814 input_exec_order_action: *mut c_void,
2815 rsp_info: *mut c_void,
2816 request_id: c_int,
2817 is_last: c_int,
2818) {
2819 unsafe {
2820 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2821 if let Some(ref mut handler) = api.handler {
2822 let parsed_input_exec_order_action = if !input_exec_order_action.is_null() {
2823 let exec_action_ptr =
2824 input_exec_order_action as *const InputExecOrderActionField;
2825 Some((*exec_action_ptr).clone())
2826 } else {
2827 None
2828 };
2829
2830 let parsed_rsp_info = if !rsp_info.is_null() {
2831 let info_ptr = rsp_info as *const RspInfoField;
2832 Some((*info_ptr).clone())
2833 } else {
2834 None
2835 };
2836
2837 handler.on_rsp_exec_order_action(
2838 parsed_input_exec_order_action,
2839 parsed_rsp_info,
2840 request_id,
2841 is_last != 0,
2842 );
2843 }
2844 }
2845 }
2846}
2847
2848extern "C" fn on_rsp_for_quote_insert_callback(
2849 user_data: *mut c_void,
2850 input_for_quote: *mut c_void,
2851 rsp_info: *mut c_void,
2852 request_id: c_int,
2853 is_last: c_int,
2854) {
2855 unsafe {
2856 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2857 if let Some(ref mut handler) = api.handler {
2858 let parsed_input_for_quote = if !input_for_quote.is_null() {
2859 let for_quote_ptr = input_for_quote as *const InputForQuoteField;
2860 Some((*for_quote_ptr).clone())
2861 } else {
2862 None
2863 };
2864
2865 let parsed_rsp_info = if !rsp_info.is_null() {
2866 let info_ptr = rsp_info as *const RspInfoField;
2867 Some((*info_ptr).clone())
2868 } else {
2869 None
2870 };
2871
2872 handler.on_rsp_for_quote_insert(
2873 parsed_input_for_quote,
2874 parsed_rsp_info,
2875 request_id,
2876 is_last != 0,
2877 );
2878 }
2879 }
2880 }
2881}
2882
2883extern "C" fn on_rsp_quote_insert_callback(
2884 user_data: *mut c_void,
2885 input_quote: *mut c_void,
2886 rsp_info: *mut c_void,
2887 request_id: c_int,
2888 is_last: c_int,
2889) {
2890 unsafe {
2891 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2892 if let Some(ref mut handler) = api.handler {
2893 let parsed_input_quote = if !input_quote.is_null() {
2894 let quote_ptr = input_quote as *const InputQuoteField;
2895 Some((*quote_ptr).clone())
2896 } else {
2897 None
2898 };
2899
2900 let parsed_rsp_info = if !rsp_info.is_null() {
2901 let info_ptr = rsp_info as *const RspInfoField;
2902 Some((*info_ptr).clone())
2903 } else {
2904 None
2905 };
2906
2907 handler.on_rsp_quote_insert(
2908 parsed_input_quote,
2909 parsed_rsp_info,
2910 request_id,
2911 is_last != 0,
2912 );
2913 }
2914 }
2915 }
2916}
2917
2918extern "C" fn on_rsp_quote_action_callback(
2919 user_data: *mut c_void,
2920 input_quote_action: *mut c_void,
2921 rsp_info: *mut c_void,
2922 request_id: c_int,
2923 is_last: c_int,
2924) {
2925 unsafe {
2926 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2927 if let Some(ref mut handler) = api.handler {
2928 let parsed_input_quote_action = if !input_quote_action.is_null() {
2929 let quote_action_ptr = input_quote_action as *const InputQuoteActionField;
2930 Some((*quote_action_ptr).clone())
2931 } else {
2932 None
2933 };
2934
2935 let parsed_rsp_info = if !rsp_info.is_null() {
2936 let info_ptr = rsp_info as *const RspInfoField;
2937 Some((*info_ptr).clone())
2938 } else {
2939 None
2940 };
2941
2942 handler.on_rsp_quote_action(
2943 parsed_input_quote_action,
2944 parsed_rsp_info,
2945 request_id,
2946 is_last != 0,
2947 );
2948 }
2949 }
2950 }
2951}
2952
2953extern "C" fn on_rsp_batch_order_action_callback(
2954 user_data: *mut c_void,
2955 input_batch_order_action: *mut c_void,
2956 rsp_info: *mut c_void,
2957 request_id: c_int,
2958 is_last: c_int,
2959) {
2960 unsafe {
2961 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2962 if let Some(ref mut handler) = api.handler {
2963 let parsed_input_batch_order_action = if !input_batch_order_action.is_null() {
2964 let batch_action_ptr =
2965 input_batch_order_action as *const InputBatchOrderActionField;
2966 Some((*batch_action_ptr).clone())
2967 } else {
2968 None
2969 };
2970
2971 let parsed_rsp_info = if !rsp_info.is_null() {
2972 let info_ptr = rsp_info as *const RspInfoField;
2973 Some((*info_ptr).clone())
2974 } else {
2975 None
2976 };
2977
2978 handler.on_rsp_batch_order_action(
2979 parsed_input_batch_order_action,
2980 parsed_rsp_info,
2981 request_id,
2982 is_last != 0,
2983 );
2984 }
2985 }
2986 }
2987}
2988
2989extern "C" fn on_rsp_remove_parked_order_callback(
2990 user_data: *mut c_void,
2991 remove_parked_order: *mut c_void,
2992 rsp_info: *mut c_void,
2993 request_id: c_int,
2994 is_last: c_int,
2995) {
2996 unsafe {
2997 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
2998 if let Some(ref mut handler) = api.handler {
2999 let parsed_remove_parked_order = if !remove_parked_order.is_null() {
3000 let remove_ptr = remove_parked_order as *const RemoveParkedOrderField;
3001 Some((*remove_ptr).clone())
3002 } else {
3003 None
3004 };
3005
3006 let parsed_rsp_info = if !rsp_info.is_null() {
3007 let info_ptr = rsp_info as *const RspInfoField;
3008 Some((*info_ptr).clone())
3009 } else {
3010 None
3011 };
3012
3013 handler.on_rsp_remove_parked_order(
3014 parsed_remove_parked_order,
3015 parsed_rsp_info,
3016 request_id,
3017 is_last != 0,
3018 );
3019 }
3020 }
3021 }
3022}
3023
3024extern "C" fn on_rsp_remove_parked_order_action_callback(
3025 user_data: *mut c_void,
3026 remove_parked_order_action: *mut c_void,
3027 rsp_info: *mut c_void,
3028 request_id: c_int,
3029 is_last: c_int,
3030) {
3031 unsafe {
3032 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3033 if let Some(ref mut handler) = api.handler {
3034 let parsed_remove_parked_order_action = if !remove_parked_order_action.is_null() {
3035 let remove_action_ptr =
3036 remove_parked_order_action as *const RemoveParkedOrderActionField;
3037 Some((*remove_action_ptr).clone())
3038 } else {
3039 None
3040 };
3041
3042 let parsed_rsp_info = if !rsp_info.is_null() {
3043 let info_ptr = rsp_info as *const RspInfoField;
3044 Some((*info_ptr).clone())
3045 } else {
3046 None
3047 };
3048
3049 handler.on_rsp_remove_parked_order_action(
3050 parsed_remove_parked_order_action,
3051 parsed_rsp_info,
3052 request_id,
3053 is_last != 0,
3054 );
3055 }
3056 }
3057 }
3058}
3059
3060extern "C" fn on_rsp_qry_max_order_volume_callback(
3061 user_data: *mut c_void,
3062 qry_max_order_volume: *mut c_void,
3063 rsp_info: *mut c_void,
3064 request_id: c_int,
3065 is_last: c_int,
3066) {
3067 unsafe {
3068 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3069 if let Some(ref mut handler) = api.handler {
3070 let parsed_qry_max_order_volume = if !qry_max_order_volume.is_null() {
3071 let max_volume_ptr = qry_max_order_volume as *const QryMaxOrderVolumeField;
3072 Some((*max_volume_ptr).clone())
3073 } else {
3074 None
3075 };
3076
3077 let parsed_rsp_info = if !rsp_info.is_null() {
3078 let info_ptr = rsp_info as *const RspInfoField;
3079 Some((*info_ptr).clone())
3080 } else {
3081 None
3082 };
3083
3084 handler.on_rsp_qry_max_order_volume(
3085 parsed_qry_max_order_volume,
3086 parsed_rsp_info,
3087 request_id,
3088 is_last != 0,
3089 );
3090 }
3091 }
3092 }
3093}
3094
3095extern "C" fn on_rsp_qry_depth_market_data_callback(
3096 user_data: *mut c_void,
3097 depth_market_data: *mut c_void,
3098 rsp_info: *mut c_void,
3099 request_id: c_int,
3100 is_last: c_int,
3101) {
3102 unsafe {
3103 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3104 if let Some(ref mut handler) = api.handler {
3105 let parsed_depth_market_data = if !depth_market_data.is_null() {
3106 let market_data_ptr = depth_market_data as *const DepthMarketDataField;
3107 Some((*market_data_ptr).clone())
3108 } else {
3109 None
3110 };
3111
3112 let parsed_rsp_info = if !rsp_info.is_null() {
3113 let info_ptr = rsp_info as *const RspInfoField;
3114 Some((*info_ptr).clone())
3115 } else {
3116 None
3117 };
3118
3119 handler.on_rsp_qry_depth_market_data(
3120 parsed_depth_market_data,
3121 parsed_rsp_info,
3122 request_id,
3123 is_last != 0,
3124 );
3125 }
3126 }
3127 }
3128}
3129
3130extern "C" fn on_rsp_qry_settlement_info_callback(
3131 user_data: *mut c_void,
3132 settlement_info: *mut c_void,
3133 rsp_info: *mut c_void,
3134 request_id: c_int,
3135 is_last: c_int,
3136) {
3137 unsafe {
3138 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3139 if let Some(ref mut handler) = api.handler {
3140 let parsed_settlement_info = if !settlement_info.is_null() {
3141 let settlement_ptr = settlement_info as *const SettlementInfoField;
3142 Some((*settlement_ptr).clone())
3143 } else {
3144 None
3145 };
3146
3147 let parsed_rsp_info = if !rsp_info.is_null() {
3148 let info_ptr = rsp_info as *const RspInfoField;
3149 Some((*info_ptr).clone())
3150 } else {
3151 None
3152 };
3153
3154 handler.on_rsp_qry_settlement_info(
3155 parsed_settlement_info,
3156 parsed_rsp_info,
3157 request_id,
3158 is_last != 0,
3159 );
3160 }
3161 }
3162 }
3163}
3164
3165extern "C" fn on_rsp_qry_transfer_bank_callback(
3166 user_data: *mut c_void,
3167 transfer_bank: *mut c_void,
3168 rsp_info: *mut c_void,
3169 request_id: c_int,
3170 is_last: c_int,
3171) {
3172 unsafe {
3173 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3174 if let Some(ref mut handler) = api.handler {
3175 let parsed_transfer_bank = if !transfer_bank.is_null() {
3176 let bank_ptr = transfer_bank as *const TransferBankField;
3177 Some((*bank_ptr).clone())
3178 } else {
3179 None
3180 };
3181
3182 let parsed_rsp_info = if !rsp_info.is_null() {
3183 let info_ptr = rsp_info as *const RspInfoField;
3184 Some((*info_ptr).clone())
3185 } else {
3186 None
3187 };
3188
3189 handler.on_rsp_qry_transfer_bank(
3190 parsed_transfer_bank,
3191 parsed_rsp_info,
3192 request_id,
3193 is_last != 0,
3194 );
3195 }
3196 }
3197 }
3198}
3199
3200extern "C" fn on_rsp_qry_investor_position_detail_callback(
3201 user_data: *mut c_void,
3202 investor_position_detail: *mut c_void,
3203 rsp_info: *mut c_void,
3204 request_id: c_int,
3205 is_last: c_int,
3206) {
3207 unsafe {
3208 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3209 if let Some(ref mut handler) = api.handler {
3210 let parsed_investor_position_detail = if !investor_position_detail.is_null() {
3211 let detail_ptr = investor_position_detail as *const InvestorPositionDetailField;
3212 Some((*detail_ptr).clone())
3213 } else {
3214 None
3215 };
3216
3217 let parsed_rsp_info = if !rsp_info.is_null() {
3218 let info_ptr = rsp_info as *const RspInfoField;
3219 Some((*info_ptr).clone())
3220 } else {
3221 None
3222 };
3223
3224 handler.on_rsp_qry_investor_position_detail(
3225 parsed_investor_position_detail,
3226 parsed_rsp_info,
3227 request_id,
3228 is_last != 0,
3229 );
3230 }
3231 }
3232 }
3233}
3234
3235extern "C" fn on_rsp_qry_notice_callback(
3236 user_data: *mut c_void,
3237 notice: *mut c_void,
3238 rsp_info: *mut c_void,
3239 request_id: c_int,
3240 is_last: c_int,
3241) {
3242 unsafe {
3243 if let Some(api) = (user_data as *mut TraderApi).as_mut() {
3244 if let Some(ref mut handler) = api.handler {
3245 let parsed_notice = if !notice.is_null() {
3246 let notice_ptr = notice as *const NoticeField;
3247 Some((*notice_ptr).clone())
3248 } else {
3249 None
3250 };
3251
3252 let parsed_rsp_info = if !rsp_info.is_null() {
3253 let info_ptr = rsp_info as *const RspInfoField;
3254 Some((*info_ptr).clone())
3255 } else {
3256 None
3257 };
3258
3259 handler.on_rsp_qry_notice(parsed_notice, parsed_rsp_info, request_id, is_last != 0);
3260 }
3261 }
3262 }
3263}
3264
3265impl Drop for TraderApi {
3266 fn drop(&mut self) {
3267 self.release();
3268 }
3269}
3270
3271#[cfg(test)]
3272mod tests {
3273 use super::*;
3274
3275 #[test]
3276 fn test_version() {
3277 match TraderApi::get_version() {
3279 Ok(version) => eprintln!("版本: {}", version),
3280 Err(e) => eprintln!("获取版本失败: {}", e),
3281 }
3282 }
3283}