#![allow(unused_variables)]
use std::{env::var, path::Path, sync::Arc};
use ctp_dyn::{
copy_str_to_i8_array, gb18030_cstr_i8_to_str, print_rsp_info,
v1alpha1::get_api_version,
v1alpha1::{
CThostFtdcDepthMarketDataField, CThostFtdcReqUserLoginField, CThostFtdcRspInfoField,
CThostFtdcRspUserLoginField, CThostFtdcSpecificInstrumentField, MdApi, MdSpi,
},
SetString, WrapToString,
};
pub struct BaseMdSpi {
pub(crate) mdapi: Arc<MdApi>,
}
impl MdSpi for BaseMdSpi {
fn on_front_connected(&mut self) {
let mut req = CThostFtdcReqUserLoginField::default();
println!("mdspi.on_front_connected !!!");
let user_id = var("SIMNOW_USER_0").unwrap();
let password = var("SIMNOW_PASS_0").unwrap();
println!("user_id: {}", user_id);
copy_str_to_i8_array(&mut req.UserID, user_id.as_str());
req.BrokerID.set_str("9999");
req.Password.set_str(&password);
self.mdapi.req_user_login(&mut req, 1);
}
fn on_rsp_user_login(
&mut self,
rsp_user_login: Option<&CThostFtdcRspUserLoginField>,
rsp_info: Option<&CThostFtdcRspInfoField>,
request_id: i32,
is_last: bool,
) {
print_rsp_info!(rsp_info);
println!(
"on_rsp_user_login! request_id[{}], is_last[{}]",
request_id, is_last
);
if is_last {
let instrument_ids = vec!["ag2508".to_string(), "TL2506".to_string()];
println!("instruments: {:?}", instrument_ids);
let ret = self.mdapi.subscribe_market_data(&instrument_ids);
println!("sub ret: {}", ret)
}
}
fn on_rsp_sub_market_data(
&mut self,
specific_instrument: Option<&CThostFtdcSpecificInstrumentField>,
rsp_info: Option<&CThostFtdcRspInfoField>,
request_id: i32,
is_last: bool,
) {
print_rsp_info!(rsp_info);
println!(
"on_rsp_sub_market_data: instrument_id[{:?}], reqid[{:?}], is_last[{:?}]",
gb18030_cstr_i8_to_str(&specific_instrument.unwrap().InstrumentID),
request_id,
is_last
);
}
fn on_rtn_depth_market_data(
&mut self,
depth_market_data: Option<&CThostFtdcDepthMarketDataField>,
) {
println!("OnRtnDepthMarketData!");
if let Some(q) = depth_market_data {
println!(
"[{} {}.{:03}] {} => last_price: {}, ask_price1: {}:{}, ask_price2: {}:{}",
q.ActionDay.to_string(),
q.UpdateTime.to_string(),
q.UpdateMillisec,
gb18030_cstr_i8_to_str(&q.InstrumentID).unwrap(),
q.LastPrice,
q.AskPrice1,
q.AskVolume1,
q.AskPrice2,
q.AskVolume2,
);
} else {
panic!("tick null!");
};
}
}
fn main() {
println!("mdapi start here!");
let base_dir = var("CARGO_MANIFEST_DIR").unwrap();
println!("base_dir: {base_dir}");
#[cfg(target_os = "macos")]
let dynlib_path =
"./api/ctp/v6.7.2/v6.7.2_MacOS_20231016/thostmduserapi_se.framework/thostmduserapi_se";
#[cfg(target_os = "linux")]
let dynlib_path =
"./api/ctp/v6.7.2/v6.7.2_20230913_api_traderapi_se_linux64/thostmduserapi_se.so";
let dynlib_path = Path::new(&base_dir).join(dynlib_path);
let mdapi = MdApi::create_api(dynlib_path.clone(), "./md_", false, false);
let mdapi = Arc::new(mdapi);
let base_mdspi: BaseMdSpi = BaseMdSpi {
mdapi: Arc::clone(&mdapi),
};
let mdspi_box: Box<BaseMdSpi> = Box::new(base_mdspi);
println!("get_api_version: {}", mdapi.get_api_version());
match get_api_version(dynlib_path) {
Ok(x) => {
println!("api version: {}", x);
}
Err(e) => {
println!("error: {:?}", e);
}
}
mdapi.register_front("tcp://180.168.146.187:10131");
let mdspi_ptr = Box::into_raw(mdspi_box) as *mut dyn MdSpi;
let mdspi_ptr2 = mdspi_ptr.clone();
mdapi.register_spi(mdspi_ptr);
mdapi.init();
println!("mdapi init");
mdapi.join();
let _ = unsafe { Box::from_raw(mdspi_ptr2) };
}