strategy.rs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. use std::cmp::{max, min};
  2. use std::collections::HashMap;
  3. use std::ops::{Div, Mul};
  4. use chrono::Utc;
  5. use rust_decimal::Decimal;
  6. use rust_decimal::prelude::{FromPrimitive, ToPrimitive};
  7. use rust_decimal_macros::dec;
  8. use crate::model::{LocalPosition, OrderInfo};
  9. use crate::utils;
  10. use tracing::{info, error, warn};
  11. use global::params::Params;
  12. use standard::{OrderCommand};
  13. use crate::predictor::Predictor;
  14. #[derive(Debug)]
  15. pub struct Strategy {
  16. // 各类时间戳和时延,我们都改成了毫秒级
  17. pub _print_time: i64, // 上次打印时间
  18. pub _print_interval: i64, // 打印时延
  19. pub _start_time: i64, // 开始时间
  20. pub local_time: i64, // 本地时间
  21. pub local_start_time: i64, // 本地开始时间
  22. pub post_open_time: i64, // 上次提交订单的时间戳
  23. pub post_open_interval: i64, // 提交订单时延
  24. pub _check_local_orders_time: i64, // 上次查单时间
  25. pub _check_local_orders_interval: i64, // 查单间距,原文是秒级,这里改成毫秒级
  26. pub in_cancel: HashMap<String, i64>, // 撤单队列
  27. pub cancel_wait_interval: i64, // 取消等待时延
  28. pub in_check: HashMap<String, i64>, // 查单队列
  29. pub check_wait_interval: i64, // 检测时延
  30. pub request_limit_check_time: i64, // 上次检查订单的时间
  31. pub request_limit_check_interval: i64, // 原文是秒级,这里改成毫秒级
  32. pub request_count: i64, // 记录请求次数,原文的request_num
  33. pub request_order_count: i64, // 记录下单次数,原文的request_order_num
  34. pub request_over_log_interval: i64, // 两次超时打印之间的间隔
  35. pub request_over_log_time: i64, // 上次打印时间
  36. pub limit_requests_num: i64, // 单位(时延)时间内请求次数上限
  37. pub limit_order_requests_num: i64, // 单位(时延)时间内下单次数上限
  38. pub _req_num_per_window: i64, // 单位(时延)时间内请求上限窗口
  39. pub params: Params, //
  40. pub exchange: String, //
  41. pub broker_id: String, //
  42. pub trade_name: String, //
  43. pub ref_exchange_length: usize, //
  44. pub ref_name: Vec<String>, //
  45. pub maker_mode: String, //
  46. pub local_orders: HashMap<String, OrderInfo>, // 本地订单
  47. pub pos: LocalPosition, //
  48. pub long_hold_value: Decimal, //
  49. pub short_hold_value: Decimal, //
  50. pub equity: Decimal, //
  51. pub coin: Decimal, //
  52. pub cash: Decimal, //
  53. pub start_equity: Decimal, //
  54. pub start_coin: Decimal, //
  55. pub start_cash: Decimal, //
  56. pub max_equity: Decimal, //
  57. pub local_profit: Decimal, //
  58. pub total_amount: Decimal, //
  59. pub is_ready: bool, // 程序是否已经准备好,ready
  60. pub _is_print: bool, //
  61. pub mp_ema: Decimal, // 原文的mp_ewma
  62. pub mp: Decimal, //
  63. pub bp: Decimal, //
  64. pub ap: Decimal, //
  65. pub ref_price: Decimal, //
  66. pub ref_bp: Decimal, //
  67. pub ref_ap: Decimal, //
  68. pub step_size: Decimal, // 原文的stepSize
  69. pub tick_size: Decimal, // 原文的tickSize
  70. pub min_amount_value: Decimal, // 最小下单价值
  71. pub max_amount_value: Decimal, // 最大下单价值
  72. pub max_pos_rate: Decimal, // 原文的maxPos,其实是最大持仓比例
  73. pub profit: Decimal, //
  74. pub daily_return: Decimal, //
  75. pub adjust_lever_rate: Decimal, // 原文的adjust_leverrate
  76. pub lever_rate: Decimal, // 原文的leverrate
  77. pub long_pos_bias: Decimal, // 做多浮盈
  78. pub short_pos_bias: Decimal, // 做空浮盈
  79. pub long_hold_rate: Decimal, //
  80. pub short_hold_rate: Decimal, //
  81. pub max_long_value: Decimal, // 最大做多持仓
  82. pub max_short_value: Decimal, // 最大做空持仓
  83. pub open_dist: Vec<Decimal>, // 开仓相关价格
  84. pub close_dist: Vec<Decimal>, // 平仓相关价格
  85. pub trade_close_dist: Decimal, //
  86. pub trade_open_dist: Decimal, //
  87. pub ref_index: usize, //
  88. pub predict: Decimal, //
  89. pub predict_alpha: Decimal, //
  90. pub trade_vol_24h_w: Decimal, // 24小时成交额(单位:万)
  91. pub grid: Decimal, // 网格数量
  92. }
  93. impl Strategy {
  94. pub fn new(params: &Params, is_print: bool) -> Self {
  95. if params.ref_exchange.len() != params.ref_pair.len(){
  96. error!("参考盘口数不等于参考品种数,退出,请检查配置!");
  97. panic!("参考盘口数不等于参考品种数,退出,请检查配置!");
  98. }
  99. // strategy的初始化,里面已经有一些参数初始化了
  100. let mut strategy = Self {
  101. _print_time: 0,
  102. _start_time: 0,
  103. local_time: 0,
  104. local_start_time: 0,
  105. request_count: 0,
  106. request_order_count: 0,
  107. request_over_log_interval: 60 * 1000,
  108. request_over_log_time: 0,
  109. _print_interval: 5 * 1000,
  110. in_cancel: Default::default(),
  111. cancel_wait_interval: (0.2 * 1000f64).to_i64().unwrap(),
  112. in_check: Default::default(),
  113. check_wait_interval: 10 * 1000,
  114. _check_local_orders_time: 0,
  115. _check_local_orders_interval: 0,
  116. request_limit_check_time: 0,
  117. request_limit_check_interval: 0,
  118. limit_requests_num: 0,
  119. limit_order_requests_num: 0,
  120. _req_num_per_window: 0,
  121. post_open_time: 0,
  122. post_open_interval: 0,
  123. params: params.clone(),
  124. exchange: params.exchange.clone(),
  125. broker_id: params.broker_id.clone(),
  126. trade_name: "".to_string(),
  127. ref_exchange_length: params.ref_exchange.len(),
  128. ref_name: vec![],
  129. maker_mode: "free".to_string(),
  130. local_orders: Default::default(),
  131. pos: LocalPosition {
  132. long_pos: Default::default(),
  133. short_pos: Default::default(),
  134. long_avg: Default::default(),
  135. short_avg: Default::default(),
  136. },
  137. long_hold_value: Default::default(),
  138. short_hold_value: Default::default(),
  139. equity: Default::default(),
  140. coin: Default::default(),
  141. cash: Default::default(),
  142. start_equity: Default::default(),
  143. start_coin: Default::default(),
  144. start_cash: Default::default(),
  145. max_equity: Default::default(),
  146. local_profit: Default::default(),
  147. total_amount: Default::default(),
  148. is_ready: false,
  149. _is_print: is_print,
  150. min_amount_value: dec!(0.01),
  151. max_amount_value: dec!(10000.0),
  152. mp_ema: Default::default(),
  153. mp: Default::default(),
  154. bp: Default::default(),
  155. ap: Default::default(),
  156. ref_price: Default::default(),
  157. ref_bp: Default::default(),
  158. ref_ap: Default::default(),
  159. step_size: dec!(1e-10),
  160. tick_size: dec!(1e-10),
  161. max_pos_rate: Default::default(),
  162. profit: Default::default(),
  163. daily_return: Default::default(),
  164. adjust_lever_rate: Decimal::ONE,
  165. lever_rate: Default::default(),
  166. long_pos_bias: Default::default(),
  167. short_pos_bias: Default::default(),
  168. long_hold_rate: Default::default(),
  169. short_hold_rate: Default::default(),
  170. max_long_value: Default::default(),
  171. max_short_value: Default::default(),
  172. open_dist: vec![],
  173. close_dist: vec![],
  174. trade_close_dist: params.close,
  175. trade_open_dist: params.open,
  176. ref_index: 0,
  177. predict: Default::default(),
  178. predict_alpha: Default::default(),
  179. trade_vol_24h_w: Default::default(),
  180. grid: Decimal::from(params.grid),
  181. };
  182. // 交易名字
  183. strategy.trade_name = format!("{}@{}", params.exchange.clone(), params.pair.clone());
  184. // 参考交易所的trade_name
  185. for index in 0..strategy.ref_exchange_length {
  186. strategy.ref_name.push(format!("{}@{}", params.ref_exchange[index], params.ref_pair[index]));
  187. }
  188. // 杠杆比例处理
  189. strategy.lever_rate = params.lever_rate;
  190. if strategy.exchange.contains("spot") {
  191. strategy.lever_rate = min(params.lever_rate, Decimal::ONE);
  192. }
  193. // 各类时间戳
  194. let now = Utc::now();
  195. strategy.local_time = now.timestamp_millis();
  196. strategy.local_start_time = now.timestamp_millis();
  197. strategy._print_time = now.timestamp_millis();
  198. strategy._start_time = now.timestamp_millis();
  199. // 检查订单的时间戳
  200. strategy._check_local_orders_time = now.timestamp_millis();
  201. strategy._check_local_orders_interval = 10 * 1000;
  202. // 下单的相关限制处理
  203. strategy.request_limit_check_time = now.timestamp_millis();
  204. strategy.request_limit_check_interval = 10 * 1000;
  205. // 求得正常请求数量和下单请求数量(interval时间内)
  206. let request_limit_check_interval_per_second = strategy.request_limit_check_interval / 1000;
  207. strategy.limit_requests_num = utils::get_limit_requests_num_per_second(params.exchange.clone()) * (request_limit_check_interval_per_second);
  208. strategy.limit_order_requests_num = utils::get_limit_order_requests_num_per_second(params.exchange.clone()) * (request_limit_check_interval_per_second);
  209. // 开仓下单间隔 均匀下单机会
  210. strategy.post_open_time = now.timestamp_millis();
  211. let post_open_interval_per_second = Decimal::ONE.div(Decimal::from_i64(utils::get_limit_order_requests_num_per_second(params.exchange.clone())).unwrap());
  212. strategy.post_open_interval = dec!(1000).mul(post_open_interval_per_second).to_i64().unwrap();
  213. info!("策略模块初始化完成!");
  214. return strategy;
  215. }
  216. // 更新当前strategy的各类信息
  217. // #[instrument(skip(self, trader_msg), level="TRACE")]
  218. pub fn _update_data(&mut self,
  219. local_position: &LocalPosition,
  220. local_coin: &Decimal,
  221. local_cash: &Decimal,
  222. predictor: &Predictor) -> bool {
  223. // position信息更新
  224. if self.pos.long_pos != local_position.long_pos {
  225. self.pos.long_pos = local_position.long_pos;
  226. self.pos.long_avg = local_position.long_avg;
  227. }
  228. if self.pos.short_pos != local_position.short_pos {
  229. self.pos.short_pos = local_position.short_pos;
  230. self.pos.short_avg = local_position.short_avg;
  231. }
  232. // 价格值处理
  233. self.bp = predictor.bid_price;
  234. self.ap = predictor.ask_price;
  235. self.mp = (self.bp + self.ap) * dec!(0.5);
  236. // 中间价的ema值处理
  237. if self.mp_ema.eq(&Decimal::ZERO) {
  238. self.mp_ema = self.mp;
  239. } else {
  240. self.mp_ema = self.mp_ema * dec!(0.999) + self.mp * dec!(0.001);
  241. }
  242. // 动态杠杆调节
  243. if self.mp > self.mp_ema {
  244. self.adjust_lever_rate = Decimal::ONE;
  245. } else {
  246. self.adjust_lever_rate = dec!(0.8);
  247. }
  248. // 当前持仓价值处理
  249. self.long_hold_value = self.pos.long_pos * self.mp;
  250. self.short_hold_value = self.pos.short_pos * self.mp;
  251. self.max_long_value = self.equity * self.lever_rate * self.adjust_lever_rate;
  252. self.max_short_value = self.max_long_value;
  253. // 更新当前账户余额
  254. self.coin = local_coin.clone();
  255. self.cash = local_cash.clone();
  256. self.equity = local_cash + local_coin * self.mp;
  257. if self.equity > self.max_equity {
  258. self.max_equity = self.equity;
  259. }
  260. // 总可开数量
  261. self.total_amount = self.equity * self.lever_rate * self.adjust_lever_rate / self.mp;
  262. self.total_amount = utils::fix_amount(self.total_amount, self.step_size);
  263. if self.total_amount.eq(&Decimal::ZERO) {
  264. error!("总可开数量低于一张,请尝试加大杠杆倍数或资金!equity={}, lever_rate={}, adjust_lever_rate={}, mp={}, step_size={}",
  265. self.equity, self.lever_rate, self.adjust_lever_rate, self.mp, self.step_size);
  266. return false;
  267. }
  268. // 求最大pos
  269. if self.equity > Decimal::ZERO {
  270. let max_pos_rate = max(self.pos.long_pos, self.pos.short_pos) * self.mp / self.equity;
  271. if max_pos_rate > self.max_pos_rate {
  272. self.max_pos_rate = max_pos_rate;
  273. }
  274. // debug!(?max_pos_rate, ?self.max_pos_rate);
  275. }
  276. return true;
  277. }
  278. // 打印状态信息
  279. // 耗时700微秒
  280. // #[instrument(skip(self), level="TRACE")]
  281. pub fn _print_summary(&mut self) {
  282. self.mp.rescale(10);
  283. self.ref_price.rescale(10);
  284. self.equity.rescale(3);
  285. self.cash.rescale(3);
  286. let mut value = self.coin * self.mp;
  287. value.rescale(3);
  288. let mut price_bias = Decimal::ONE_HUNDRED * (self.ref_price - self.mp) / self.mp;
  289. price_bias.rescale(2);
  290. // 盈亏计算
  291. self.profit = if self.start_equity.gt(&Decimal::ZERO) {
  292. ((self.equity - self.start_equity) / self.start_equity) * Decimal::ONE_HUNDRED
  293. } else {
  294. Decimal::ZERO
  295. };
  296. self.profit.rescale(2);
  297. // 多仓杠杆计算
  298. let mut long_pos_leverage = if self.equity.gt(&Decimal::ZERO) {
  299. self.pos.long_pos * self.mp / self.equity
  300. } else {
  301. Decimal::ZERO
  302. };
  303. long_pos_leverage.rescale(3);
  304. // 多仓浮盈计算
  305. self.long_pos_bias = if self.pos.long_pos.gt(&Decimal::ZERO) {
  306. Decimal::ONE_HUNDRED - Decimal::ONE_HUNDRED * self.pos.long_avg / self.mp
  307. } else {
  308. Decimal::ZERO
  309. };
  310. self.long_pos_bias.rescale(2);
  311. // 空仓杠杆计算
  312. let mut short_pos_leverage = if self.equity.gt(&Decimal::ZERO) {
  313. self.pos.short_pos * self.mp / self.equity
  314. } else {
  315. Decimal::ZERO
  316. };
  317. short_pos_leverage.rescale(3);
  318. // 多仓浮盈计算
  319. self.short_pos_bias = if self.pos.short_pos.gt(&Decimal::ZERO) {
  320. Decimal::ONE_HUNDRED - Decimal::ONE_HUNDRED * self.pos.short_avg / self.mp
  321. } else {
  322. Decimal::ZERO
  323. };
  324. let run_time = Utc::now().timestamp_millis() - self._start_time;
  325. let run_time_day = Decimal::from(run_time) / (dec!(86400000));
  326. self.daily_return = self.profit / run_time_day;
  327. self.daily_return.rescale(2);
  328. self.short_pos_bias.rescale(2);
  329. self.trade_open_dist.rescale(6);
  330. self.trade_close_dist.rescale(6);
  331. self.predict.rescale(5);
  332. info!("------------------当前状态-------------------");
  333. info!("[品种 {}, 现价 {:?}, 定价 {:?}, 偏差 {:?}%, 杠杆 {:?}, 动态{:?}, 预估24H成交额 {:?}万], ",
  334. self.params.pair, self.mp, self.ref_price, price_bias, self.lever_rate,
  335. self.adjust_lever_rate, self.trade_vol_24h_w);
  336. info!("[净值 {:?}, Cash {:?}, Coin(价值) {:?}, 日化 {:?}%], ",
  337. self.equity, self.cash, value, self.daily_return);
  338. info!("[推算利润 {:?}, 盈亏 {:?}%, 做多杠杆 {:?}%, 做多浮盈 {:?}%, 做空杠杆 {:?}%, 做空浮盈 {:?}%], ",
  339. self.local_profit, self.profit, long_pos_leverage, self.long_pos_bias, short_pos_leverage, self.short_pos_bias);
  340. }
  341. // 取消目标方向订单,原文是_cancel_targit_side_orders
  342. // #[instrument(skip(self, command), level="TRACE")]
  343. pub fn _cancel_target_side_orders(&self, command: &mut OrderCommand) {
  344. // 要取消的目标方向
  345. let target_side = vec![
  346. "kd".to_string(),
  347. "kk".to_string(),
  348. "pd".to_string(),
  349. "pk".to_string()
  350. ];
  351. // debug!(?self.local_orders);
  352. for client_id in self.local_orders.keys() {
  353. let order = self.local_orders.get(client_id).unwrap();
  354. // 如果不属于目标方向,则不需要取消
  355. if !target_side.contains(&order.side.clone()) {
  356. continue;
  357. }
  358. // 属于目标方向,则取消
  359. let key = format!("Cancel{}", client_id);
  360. let value = vec![order.client_id.clone(), order.order_id.clone()];
  361. command.cancel.insert(key, value);
  362. }
  363. // debug!(?command);
  364. }
  365. // 修复挂单价格,不然单子打不出去
  366. // #[instrument(skip(self), level="TRACE")]
  367. pub fn fix_price(&mut self, predictor: &mut Predictor) {
  368. predictor.optimal_ask_price = utils::fix_price(predictor.optimal_ask_price, self.tick_size);
  369. predictor.optimal_bid_price = utils::fix_price(predictor.optimal_bid_price, self.tick_size);
  370. // let open = self.trade_open_dist;
  371. // let close = self.trade_close_dist;
  372. // 平仓相关
  373. let close_avoid = dec!(0.0001);
  374. self.close_dist = vec![
  375. predictor.optimal_bid_price * (Decimal::ONE + close_avoid), // buy upper
  376. predictor.optimal_bid_price * (Decimal::ONE - close_avoid), // buy lower
  377. predictor.optimal_ask_price * (Decimal::ONE - close_avoid), // sell lower
  378. predictor.optimal_ask_price * (Decimal::ONE + close_avoid), // sell upper
  379. ];
  380. // debug!(?mp, ?buy_start, ?sell_start, ?avoid, ?close_dist);
  381. // 开仓相关
  382. let open_avoid = dec!(0.0001);
  383. // 用于判断价格是否出界
  384. self.open_dist = vec![
  385. predictor.optimal_bid_price * (Decimal::ONE + open_avoid), // buy upper
  386. predictor.optimal_bid_price * (Decimal::ONE - open_avoid), // buy lower
  387. predictor.optimal_ask_price * (Decimal::ONE - open_avoid), // sell lower
  388. predictor.optimal_ask_price * (Decimal::ONE + open_avoid), // sell upper
  389. ];
  390. // 修复价格范围
  391. for open_price in &mut self.open_dist {
  392. *open_price = utils::fix_price(*open_price, self.tick_size);
  393. }
  394. }
  395. // 统计请求次数
  396. // #[instrument(skip(self, command), level="TRACE")]
  397. pub fn _update_request_num(&mut self, command: &OrderCommand) {
  398. // debug!(?command);
  399. // debug!(?self.request_order_count, ?self.request_count);
  400. let order_count = (command.limits_open.len() + command.limits_close.len()).to_i64().unwrap();
  401. let request_count = order_count + (command.cancel.len() + command.check.len()).to_i64().unwrap();
  402. self.request_order_count += order_count;
  403. self.request_count += request_count;
  404. // debug!(?self.request_order_count, ?self.request_count);
  405. }
  406. // 根据平均请求次数限制开仓下单
  407. // #[instrument(skip(self, command), level="TRACE")]
  408. pub fn _check_request_limit(&mut self, command: &mut OrderCommand) {
  409. let mut msg = String::new();
  410. // 如果当前请求数超过限制
  411. if self.request_count > self.limit_requests_num {
  412. command.cancel.clear();
  413. command.check.clear();
  414. command.limits_open.clear();
  415. command.limits_close.clear();
  416. msg = format!("请求频率溢出,程序禁止任何操作!({}/{})", self.request_count, self.limit_requests_num);
  417. } else if self.request_order_count >= self.limit_order_requests_num { // 100%超过下单频率,则不再进行平仓挂单
  418. command.limits_close.clear();
  419. command.limits_open.clear();
  420. msg = format!("超过100%下单频率!程序禁止开平仓!({}/{})", self.request_order_count, self.limit_order_requests_num);
  421. } else if self.request_count > self.limit_requests_num * 5 / 10
  422. && self.request_order_count > self.limit_order_requests_num * 8 / 10 { // 超过80%,直接取消limits_open的下单指令
  423. command.limits_open.clear();
  424. msg = format!("超过80%下单频率,程序禁止开仓!({}/{})", self.request_order_count, self.limit_order_requests_num);
  425. }
  426. // 检查是否需要打印msg
  427. if !msg.is_empty() && self.local_time - self.request_over_log_time > self.request_over_log_interval {
  428. warn!("{}", msg);
  429. self.request_over_log_time = self.local_time;
  430. }
  431. }
  432. // 新增正在撤单、检查撤单队列,释放过时限制
  433. // #[instrument(skip(self), level="TRACE")]
  434. pub fn _update_in_cancel(&mut self,
  435. command: &mut OrderCommand,
  436. local_orders: &HashMap<String, OrderInfo>) {
  437. let mut new_cancel: HashMap<String, Vec<String>> = HashMap::new();
  438. for cancel_name in command.cancel.keys() {
  439. let cancel = command.cancel.get(cancel_name).unwrap();
  440. let client_id = cancel[0].clone();
  441. let mut need_limit_cancel = true;
  442. let order_some = local_orders.get(&client_id);
  443. // 判断是否在本地挂单表中
  444. if let Some(order) = order_some {
  445. let is_side_error = (order.side == "kk") || (order.side == "kd");
  446. // 如果订单创建时间大于100ms,才能有撤单操作
  447. if self.local_time - order.create_time < 100 {
  448. need_limit_cancel = false;
  449. }
  450. // 如果方向有误,直接撤单
  451. if is_side_error {
  452. need_limit_cancel = true;
  453. }
  454. }
  455. if need_limit_cancel {
  456. // 如果已经不在撤销队列里,增加到撤销队列
  457. if self.in_cancel.get(&client_id).is_none() {
  458. self.in_cancel.insert(client_id, self.local_time);
  459. new_cancel.insert(cancel_name.clone(), cancel.clone());
  460. }
  461. }
  462. }
  463. // debug!(?command);
  464. command.cancel = new_cancel;
  465. // debug!(?command);
  466. // 释放撤单限制
  467. self._release_in_cancel();
  468. }
  469. // 维护查单队列,检查是否在撤单
  470. // #[instrument(skip(self), level="TRACE")]
  471. pub fn _release_in_check(&mut self) {
  472. // debug!(?self.in_check);
  473. // 为什么要移出来:Rust不允许边循环边修改map
  474. let mut to_remove = Vec::new();
  475. for client_id in self.in_check.keys() {
  476. let time = self.in_check.get(client_id).unwrap();
  477. // 等待不超时,就不移除
  478. if self.local_time - time <= self.check_wait_interval {
  479. continue;
  480. }
  481. // 等待超时,就移除正在撤单队列
  482. // debug!("移除查单队列:{}", client_id.clone());
  483. to_remove.push(client_id.clone());
  484. }
  485. // 在后面的循环中去单独处理map的更新
  486. for client_id in to_remove {
  487. self.in_check.remove(&client_id);
  488. }
  489. // debug!(?self.in_check);
  490. }
  491. // 检查是否正在撤单
  492. // #[instrument(skip(self), level="TRACE")]
  493. pub fn _release_in_cancel(&mut self) {
  494. // debug!(?self.in_cancel);
  495. // 为什么要移出来:Rust不允许边循环边修改map
  496. let mut to_remove = Vec::new();
  497. for client_id in self.in_cancel.keys() {
  498. let time = self.in_cancel.get(client_id).unwrap();
  499. // 等待不超时,就不移除
  500. if self.local_time - time <= self.cancel_wait_interval {
  501. continue;
  502. }
  503. // 等待超时,就移除正在撤单队列
  504. // debug!("等待超过后移除正在撤单队列:{}", client_id.clone());
  505. to_remove.push(client_id.clone());
  506. }
  507. // 在后面的循环中去单独处理map的更新
  508. for client_id in to_remove {
  509. self.in_cancel.remove(&client_id);
  510. }
  511. // debug!(?self.in_cancel);
  512. }
  513. // 刷新请求限制
  514. pub fn _refresh_request_limit(&mut self) {
  515. if self.local_time - self.request_limit_check_time < self.request_limit_check_interval {
  516. return;
  517. }
  518. self._req_num_per_window = self.request_count;
  519. self.request_count = 0;
  520. self.request_order_count = 0;
  521. self.request_limit_check_time = self.local_time;
  522. }
  523. // 刷新持仓比例
  524. // #[instrument(skip(self), level="TRACE")]
  525. pub fn _pos_rate(&mut self) {
  526. // debug!(?self);
  527. if self.max_long_value > Decimal::ZERO {
  528. self.long_hold_rate = self.long_hold_value / self.max_long_value;
  529. // debug!(?self.long_hold_rate);
  530. }
  531. if self.max_short_value > Decimal::ZERO {
  532. self.short_hold_rate = self.short_hold_value / self.max_short_value;
  533. // debug!(?self.short_hold_rate);
  534. }
  535. }
  536. // 当退出时调用,全撤全平 准备退出
  537. pub fn on_exit(&mut self,
  538. predictor: &mut Predictor,
  539. local_orders: &HashMap<String, OrderInfo>,
  540. local_position: &LocalPosition,
  541. local_coin: &Decimal,
  542. local_cash: &Decimal) -> OrderCommand {
  543. let mut command = OrderCommand::new();
  544. if self._update_data(local_position, local_coin, local_cash, predictor) {
  545. if !self.check_ready() {
  546. return command;
  547. }
  548. // 取消、平掉所有
  549. self._close_all(&mut command);
  550. // 更新撤单队列
  551. self._update_in_cancel(&mut command, local_orders);
  552. // 检查限频
  553. self._check_request_limit(&mut command);
  554. // 统计请求频率
  555. self._update_request_num(&mut command);
  556. }
  557. // debug!(?command);
  558. return command;
  559. }
  560. // 休眠时调用,全撤 不再下新订单了 防止影响check_position执行
  561. pub fn on_sleep(&mut self,
  562. predictor: &mut Predictor,
  563. local_orders: &HashMap<String, OrderInfo>,
  564. local_position: &LocalPosition,
  565. local_coin: &Decimal,
  566. local_cash: &Decimal) -> OrderCommand {
  567. let mut command = OrderCommand::new();
  568. if self._update_data(local_position, local_coin, local_cash, predictor) {
  569. if !self.check_ready() {
  570. return command;
  571. }
  572. // 只是取消掉目标侧订单
  573. self._cancel_target_side_orders(&mut command);
  574. // 更新撤单队列
  575. self._update_in_cancel(&mut command, local_orders);
  576. // 检查限频
  577. self._check_request_limit(&mut command);
  578. // 统计请求频率
  579. self._update_request_num(&mut command);
  580. }
  581. // debug!(?command);
  582. return command;
  583. }
  584. // 清空所有挂单和仓位保持休眠状态
  585. // #[instrument(skip(self, command), level="TRACE")]
  586. pub fn _close_all(&self, command: &mut OrderCommand) {
  587. // 撤掉全部挂单
  588. let mut pd_amount = Decimal::ZERO;
  589. let mut pk_amount = Decimal::ZERO;
  590. // debug!(?self.local_orders);
  591. for client_id in self.local_orders.keys() {
  592. let order = self.local_orders.get(client_id).unwrap();
  593. // 命令生成
  594. let key = format!("Cancel{}", client_id);
  595. let value = vec![order.client_id.clone(), order.order_id.clone()];
  596. command.cancel.insert(key, value);
  597. // 统计部分
  598. if order.side == "pk".to_string() {
  599. pk_amount += order.amount;
  600. } else if order.side == "pd".to_string() {
  601. pd_amount += order.amount;
  602. }
  603. }
  604. // debug!(?pd_amount, ?pk_amount);
  605. // 批量挂单
  606. let need_close_long = self.pos.long_pos - pd_amount;
  607. let need_close_short = self.pos.short_pos - pk_amount;
  608. // debug!(?need_close_long, ?need_close_short);
  609. // 做多仓位平仓
  610. if need_close_long * self.mp > self.min_amount_value {
  611. let mut amount = need_close_long;
  612. // 现货要对数量精度进行限定处理
  613. if self.exchange.contains("spot") {
  614. amount = utils::fix_amount(amount, self.step_size);
  615. }
  616. let price = utils::fix_price(self.mp, self.tick_size);
  617. let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
  618. let value = vec![
  619. amount.to_string(),
  620. "pd".to_string(),
  621. price.to_string(),
  622. client_id.to_string()
  623. ];
  624. command.limits_close.insert(client_id.clone(), value);
  625. // debug!(?self.pos.long_pos, ?self.mp, ?need_close_long, ?command)
  626. }
  627. // 做空仓位平仓
  628. if need_close_short * self.mp > self.min_amount_value {
  629. let mut amount = need_close_short;
  630. if self.exchange.contains("spot") {
  631. amount = utils::fix_amount(amount, self.step_size);
  632. }
  633. let price = utils::fix_price(self.mp, self.tick_size);
  634. let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
  635. let value = vec![
  636. amount.to_string(),
  637. "pk".to_string(),
  638. price.to_string(),
  639. client_id.to_string()
  640. ];
  641. command.limits_close.insert(client_id.clone(), value);
  642. // debug!(?self.pos.short_pos, ?self.mp, ?need_close_short, ?command)
  643. }
  644. }
  645. // 检查是否完成准备,注意:原文是未准备完成返回true!!!!!!!!!!!!!!!!!!!
  646. pub fn check_ready(&mut self) -> bool {
  647. if self.is_ready {
  648. return true;
  649. }
  650. let pre_hot:i64 = 10 * 1000;
  651. if !self.mp.eq(&Decimal::ZERO) && self.local_time - self.local_start_time > pre_hot {
  652. self.is_ready = true;
  653. // debug!(?self.mp, ?self.local_time, ?self.local_start_time, ?pre_hot);
  654. info!("策略预热完毕,可以执行后续逻辑!")
  655. }
  656. return false;
  657. }
  658. // 接近整点时刻 不允许报单 防止下单bug
  659. pub fn check_allow_post_open(&self) -> bool {
  660. let local_time_second = self.local_time / 1000;
  661. let diff_time = local_time_second % (60 * 60);
  662. return diff_time > 30 && diff_time < 3570;
  663. }
  664. // 平仓订单处理命令
  665. // #[instrument(skip(self, command), level="TRACE")]
  666. pub fn _post_close(&self, command: &mut OrderCommand, local_orders: &HashMap<String, OrderInfo>, predictor: &mut Predictor) {
  667. // debug!(?command);
  668. let mut pd_amount = Decimal::ZERO;
  669. let mut pd_order_num = 0;
  670. let mut pk_amount = Decimal::ZERO;
  671. let mut pk_order_num = 0;
  672. // 各类价格
  673. let long_upper = self.close_dist[0];
  674. let long_lower = self.close_dist[1];
  675. let short_lower = self.close_dist[2];
  676. let short_upper = self.close_dist[3];
  677. // 获取当前挂单,如果超过挂单范围则取消当前平仓单
  678. for order_client_id in local_orders.keys() {
  679. let order = local_orders.get(order_client_id).unwrap();
  680. let key = format!("Cancel{}", *order_client_id);
  681. let value = vec![order.client_id.clone(), order.order_id.clone()];
  682. if order.side == "pk".to_string() {
  683. // if self.local_time - order.local_time > 500 || order.price > long_upper || order.price < long_lower {
  684. if order.price > long_upper || order.price < long_lower {
  685. command.cancel.insert(key.clone(), value.clone());
  686. }
  687. pk_amount += order.amount;
  688. pk_order_num += 1;
  689. }
  690. if order.side == "pd".to_string() {
  691. // if self.local_time - order.local_time > 500 || order.price < short_lower || order.price > short_upper {
  692. if order.price < short_lower || order.price > short_upper {
  693. command.cancel.insert(key.clone(), value.clone());
  694. }
  695. pd_amount += order.amount;
  696. pd_order_num += 1;
  697. }
  698. }
  699. // debug!(?command);
  700. // // 判断是否需要取消平仓订单
  701. // let is_need_cancel_all_close =
  702. // (pd_amount - self.pos.long_pos).abs() * self.mp > self.min_amount_value
  703. // || (pk_amount - self.pos.short_pos).abs() * self.mp > self.min_amount_value;
  704. // if is_need_cancel_all_close {
  705. // for order_client_id in local_orders.keys() {
  706. // let order = local_orders.get(order_client_id).unwrap();
  707. //
  708. // if order.side == "pk".to_string() || order.side == "pd".to_string() {
  709. // let key = format!("Cancel{}", *order_client_id);
  710. // let value = vec![order.client_id.clone(), order.order_id.clone()];
  711. //
  712. // command.cancel.insert(key, value);
  713. // }
  714. // }
  715. // }
  716. // // debug!(?command);
  717. if predictor.inventory > Decimal::ZERO && predictor.ask_delta != dec!(-2) {
  718. if pd_order_num == 0 {
  719. let mut price = (short_lower + short_upper) * dec!(0.5);
  720. // 不限制大小
  721. // price = utils::clip(price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
  722. price = utils::fix_price(price, self.tick_size);
  723. let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
  724. let order = vec![
  725. predictor.pos_amount.abs().to_string(),
  726. "pd".to_string(),
  727. price.to_string(),
  728. order_client_id.clone()
  729. ];
  730. command.limits_close.insert(order_client_id, order);
  731. // debug!(?command);
  732. }
  733. }
  734. if predictor.inventory < Decimal::ZERO && predictor.bid_delta != dec!(-2) {
  735. if pk_order_num == 0 {
  736. let mut price = (long_upper + long_lower) * dec!(0.5);
  737. // 不限制大小
  738. // price = utils::clip(price, self.bp * dec!(0.97), self.ap * dec!(1.0005));
  739. price = utils::fix_price(price, self.tick_size);
  740. let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
  741. let order = vec![
  742. predictor.pos_amount.abs().to_string(),
  743. "pk".to_string(),
  744. price.to_string(),
  745. order_client_id.clone()
  746. ];
  747. command.limits_close.insert(order_client_id, order);
  748. // debug!(?command);
  749. }
  750. }
  751. }
  752. // 生成取消订单的指令
  753. // #[instrument(skip(self, command), level="TRACE")]
  754. pub fn _cancel_open(&self, command: &mut OrderCommand, local_orders: &HashMap<String, OrderInfo>, predictor: &mut Predictor) {
  755. // debug!(?command);
  756. // 挂单范围
  757. let long_upper = self.open_dist[0];
  758. let long_lower = self.open_dist[1];
  759. let short_lower = self.open_dist[2];
  760. let short_upper = self.open_dist[3];
  761. for order_client_id in local_orders.keys() {
  762. let order = local_orders.get(order_client_id).unwrap();
  763. let key = format!("Cancel{}", *order_client_id);
  764. let value = vec![order.client_id.clone(), order.order_id.clone()];
  765. // 开多订单处理
  766. if order.side == "kd".to_string() {
  767. // 在价格范围内时不处理
  768. // if order.price <= long_upper && order.price >= long_lower {
  769. // if (self.local_time - order.local_time <= 500) && (order.price <= long_upper && order.price >= long_lower) {
  770. // if predictor.bid_price == order.price {
  771. // if self.local_time - order.local_time <= 500 {
  772. if self.local_time - order.local_time <= 500 && predictor.bid_delta != dec!(-2) && (order.price <= long_upper && order.price >= long_lower) {
  773. continue
  774. }
  775. command.cancel.insert(key, value);
  776. // debug!(?key, ?order.price, ?long_upper, ?long_lower);
  777. } else if order.side == "kk".to_string() { // 开空订单处理
  778. // 在价格范围内时不处理
  779. // if (self.local_time - order.local_time <= 500) && (order.price >= short_lower && order.price <= short_upper) {
  780. // if order.price >= short_lower && order.price <= short_upper {
  781. // if predictor.ask_price == order.price {
  782. // if self.local_time - order.local_time <= 500 {
  783. if self.local_time - order.local_time <= 500 && predictor.ask_delta != dec!(-2) && (order.price >= short_lower && order.price <= short_upper) {
  784. continue
  785. }
  786. // debug!(?key, ?order.price, ?short_lower, ?short_upper);
  787. command.cancel.insert(key, value);
  788. }
  789. }
  790. }
  791. // 超时触发查单信号
  792. // #[instrument(skip(self, command), level="TRACE")]
  793. pub fn _check_local_orders(&mut self,
  794. command: &mut OrderCommand,
  795. local_orders: &HashMap<String, OrderInfo>) {
  796. // debug!(?command);
  797. // 超时检测
  798. if self.local_time - self._check_local_orders_time < self._check_local_orders_interval {
  799. return;
  800. }
  801. // 查单指令生成主逻辑
  802. for client_id in local_orders.keys() {
  803. let check_some = self.in_check.get(client_id);
  804. // 如果在查单队列中,不需要再添加
  805. if let Some(_) = check_some {
  806. continue;
  807. }
  808. let order = local_orders.get(client_id).unwrap();
  809. // 没有超过10s的订单,不需要检查
  810. if self.local_time - order.local_time < self._check_local_orders_interval {
  811. continue;
  812. }
  813. let key = format!("Check{}", client_id);
  814. let value = vec![
  815. client_id.clone(),
  816. order.order_id.clone(),
  817. ];
  818. command.check.insert(key, value);
  819. self.in_check.insert(client_id.clone(), self.local_time);
  820. // debug!("查询订单:{:?}", client_id.clone());
  821. // debug!(?command);
  822. }
  823. // 维护查单队列
  824. self._release_in_check();
  825. // 更新查单时间
  826. self._check_local_orders_time = self.local_time;
  827. }
  828. // 开单指令生成逻辑
  829. // #[instrument(skip(self, command), level="TRACE")]
  830. pub fn _post_open(&mut self, command: &mut OrderCommand, local_orders: &HashMap<String, OrderInfo>, predictor: &mut Predictor) {
  831. // 开仓逻辑检测,主要是检测整点开仓逻辑
  832. if !self.check_allow_post_open() {
  833. return;
  834. }
  835. // 报单时延检测
  836. if self.local_time - self.post_open_time < self.post_open_interval {
  837. return;
  838. }
  839. // 报单时间更新
  840. self.post_open_time = self.local_time;
  841. // 获取当前挂单价值
  842. let mut buy_price_list: Vec<Decimal> = vec![];
  843. let mut sell_price_list: Vec<Decimal> = vec![];
  844. let mut buy_value = Decimal::ZERO;
  845. let mut sell_value = Decimal::ZERO;
  846. for client_id in local_orders.keys() {
  847. let order = local_orders.get(client_id).unwrap();
  848. if order.side == "kd".to_string() {
  849. buy_price_list.push(order.price);
  850. buy_value += order.amount * order.price;
  851. }
  852. if order.side == "kk".to_string() {
  853. sell_price_list.push(order.price);
  854. sell_value += order.amount * order.price;
  855. }
  856. }
  857. // 计算可开价值
  858. let long_free_value = self.max_long_value - self.long_hold_value - buy_value;
  859. let short_free_value = self.max_short_value - self.short_hold_value - sell_value;
  860. // debug!(?long_free_value, ?short_free_value);
  861. // // 现货要特殊处理
  862. // if self.exchange.contains("spot") {
  863. // let coin_value = self.coin * self.mp * self.lever_rate * self.adjust_lever_rate;
  864. // let cash_value = self.cash * self.lever_rate * self.adjust_lever_rate;
  865. //
  866. // long_free_value = min(cash_value, self.max_long_value) - buy_value;
  867. // short_free_value = min(coin_value, self.max_short_value) - sell_value;
  868. // }
  869. // 一手开单价值计算
  870. let one_hand_long_value = dec!(0.97) * (self.max_long_value / self.grid);
  871. let one_hand_short_value = dec!(0.97) * (self.max_short_value / self.grid);
  872. // 挂多单
  873. if buy_value == Decimal::ZERO && predictor.inventory.is_zero() && predictor.bid_delta != dec!(-2) {
  874. let mut target_buy_price = predictor.optimal_bid_price;
  875. // target_buy_price = utils::clip(target_buy_price, self.bp * dec!(0.97), self.ap * dec!(1.0005));
  876. target_buy_price = utils::fix_price(target_buy_price, self.tick_size);
  877. let amount = if predictor.inventory < Decimal::ZERO {
  878. predictor.pos_amount.abs()
  879. } else {
  880. let value = min(one_hand_long_value, long_free_value);
  881. utils::fix_amount(value / self.mp, self.step_size)
  882. };
  883. // 下单价值判定
  884. let amount_value = amount * target_buy_price;
  885. if amount_value >= self.min_amount_value || predictor.inventory < Decimal::ZERO {
  886. let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
  887. let order = vec![
  888. amount.to_string(),
  889. // if predictor.inventory < Decimal::ZERO {"pk".to_string()} else {"kd".to_string()},
  890. "kd".to_string(),
  891. target_buy_price.to_string(),
  892. client_id.clone(),
  893. ];
  894. // debug!(?order);
  895. command.limits_open.insert(client_id, order);
  896. } else {
  897. info!("下买单价值太小,要求:{},但是价格:{}, 数量:{}", self.min_amount_value, target_buy_price, amount);
  898. }
  899. }
  900. // 挂空单
  901. if sell_value == Decimal::ZERO && predictor.inventory.is_zero() && predictor.ask_delta != dec!(-2) {
  902. let mut target_sell_price = predictor.optimal_ask_price;
  903. // target_sell_price = utils::clip(target_sell_price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
  904. // 取消大小限制
  905. target_sell_price = utils::fix_price(target_sell_price, self.tick_size);
  906. let amount = if predictor.inventory > Decimal::ZERO {
  907. predictor.pos_amount.abs()
  908. } else {
  909. let value = min(one_hand_short_value, short_free_value);
  910. utils::fix_amount(value / self.mp, self.step_size)
  911. };
  912. // 下单价值不能太大,也不能太小
  913. let amount_value = amount * target_sell_price;
  914. if amount_value >= self.min_amount_value || predictor.inventory > Decimal::ZERO {
  915. let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
  916. let order = vec![
  917. amount.to_string(),
  918. // if predictor.inventory > Decimal::ZERO {"pd".to_string()} else {"kk".to_string()},
  919. "kk".to_string(),
  920. target_sell_price.to_string(),
  921. client_id.clone(),
  922. ];
  923. // debug!(?order);
  924. command.limits_open.insert(client_id, order);
  925. } else {
  926. info!("下卖单价值太小,要求:{},但是价格:{}, 数量:{}, inv={}", self.min_amount_value, target_sell_price, amount, predictor.inventory.abs());
  927. }
  928. }
  929. }
  930. // 定时打印
  931. pub fn on_time_print(&mut self) {
  932. if self.local_time - self._print_time < self._print_interval {
  933. return;
  934. }
  935. // 记录上次打印时间
  936. self._print_time = self.local_time;
  937. if !self._is_print {
  938. return;
  939. }
  940. // 准备好了的话就不打印预热中了
  941. if self.is_ready {
  942. return;
  943. }
  944. info!("预热中");
  945. }
  946. pub fn do_strategy(&mut self,
  947. predictor: &mut Predictor,
  948. local_orders: &HashMap<String, OrderInfo>,
  949. local_position: &LocalPosition,
  950. local_coin: &Decimal,
  951. local_cash: &Decimal) -> OrderCommand {
  952. let mut command = OrderCommand::new();
  953. // 检查是否准备充分
  954. if !predictor.is_ready || !self._update_data(local_position, local_coin, local_cash, predictor) {
  955. return command;
  956. }
  957. self.ref_ap = predictor.optimal_ask_price;
  958. self.ref_bp = predictor.optimal_bid_price;
  959. self.ref_price = predictor.mid_price;
  960. self.mp = predictor.mid_price;
  961. // 修复相关价格
  962. self.fix_price(predictor);
  963. self._cancel_open(&mut command, local_orders, predictor); // 撤单命令处理
  964. self._post_close(&mut command, local_orders, predictor); // 平仓单命令处理
  965. self._post_open(&mut command, local_orders, predictor); // 限价单命令处理
  966. self._check_local_orders(&mut command, local_orders); // 固定时间检查超时订单
  967. self._update_in_cancel(&mut command, local_orders); // 更新撤单队列,是一个filter
  968. self._check_request_limit(&mut command); // 限制频率,移除不合规则之订单,是一个filter
  969. self._refresh_request_limit(); // 刷新频率限制
  970. self._update_request_num(&mut command); // 统计刷新频率
  971. command
  972. }
  973. }