|
|
@@ -91,6 +91,7 @@ pub struct Strategy {
|
|
|
pub max_short_value: Decimal, // 最大做空持仓
|
|
|
|
|
|
pub open_dist: Vec<Decimal>, // 开仓相关价格
|
|
|
+ pub close_dist: Vec<Decimal>, // 平仓相关价格
|
|
|
|
|
|
pub trade_close_dist: Decimal, //
|
|
|
pub trade_open_dist: Decimal, //
|
|
|
@@ -183,6 +184,7 @@ impl Strategy {
|
|
|
max_long_value: Default::default(),
|
|
|
max_short_value: Default::default(),
|
|
|
open_dist: vec![],
|
|
|
+ close_dist: vec![],
|
|
|
trade_close_dist: params.close,
|
|
|
trade_open_dist: params.open,
|
|
|
ref_index: 0,
|
|
|
@@ -467,19 +469,27 @@ impl Strategy {
|
|
|
predictor.optimal_ask_price = utils::fix_price(predictor.optimal_ask_price, self.tick_size);
|
|
|
predictor.optimal_bid_price = utils::fix_price(predictor.optimal_bid_price, self.tick_size);
|
|
|
|
|
|
- // let delta_ask = predictor.ask_delta.clone();
|
|
|
- // let delta_bid = predictor.ask_delta.clone();
|
|
|
+ let open = self.trade_open_dist;
|
|
|
+ let close = self.trade_close_dist;
|
|
|
|
|
|
- // 开仓相关
|
|
|
- let avoid_ask = min(dec!(0.001), predictor.spread_max / predictor.ref_price);
|
|
|
- let avoid_bid = min(dec!(0.001), predictor.spread_max / predictor.ref_price);
|
|
|
+ // 平仓相关
|
|
|
+ let close_avoid = min(dec!(0.0005), close * dec!(0.5));
|
|
|
+ self.close_dist = vec![
|
|
|
+ predictor.optimal_bid_price * (Decimal::ONE + close_avoid), // buy upper
|
|
|
+ predictor.optimal_bid_price * (Decimal::ONE - close_avoid), // buy lower
|
|
|
+ predictor.optimal_ask_price * (Decimal::ONE - close_avoid), // sell lower
|
|
|
+ predictor.optimal_ask_price * (Decimal::ONE + close_avoid), // sell upper
|
|
|
+ ];
|
|
|
+ // debug!(?mp, ?buy_start, ?sell_start, ?avoid, ?close_dist);
|
|
|
|
|
|
+ // 开仓相关
|
|
|
+ let open_avoid = min(dec!(0.001), open * dec!(0.1));
|
|
|
// 用于判断价格是否出界
|
|
|
self.open_dist = vec![
|
|
|
- predictor.optimal_bid_price * (Decimal::ONE + avoid_bid), // buy upper
|
|
|
- predictor.optimal_bid_price * (Decimal::ONE - avoid_bid), // buy lower
|
|
|
- predictor.optimal_ask_price * (Decimal::ONE - avoid_ask), // sell lower
|
|
|
- predictor.optimal_ask_price * (Decimal::ONE + avoid_ask), // sell upper
|
|
|
+ predictor.optimal_bid_price * (Decimal::ONE + open_avoid), // buy upper
|
|
|
+ predictor.optimal_bid_price * (Decimal::ONE - open_avoid), // buy lower
|
|
|
+ predictor.optimal_ask_price * (Decimal::ONE - open_avoid), // sell lower
|
|
|
+ predictor.optimal_ask_price * (Decimal::ONE + open_avoid), // sell upper
|
|
|
];
|
|
|
|
|
|
// 修复价格范围
|
|
|
@@ -821,6 +831,107 @@ impl Strategy {
|
|
|
return diff_time > 30 && diff_time < 3570;
|
|
|
}
|
|
|
|
|
|
+ // 平仓订单处理命令
|
|
|
+ // #[instrument(skip(self, command), level="TRACE")]
|
|
|
+ pub fn _post_close(&self, command: &mut OrderCommand, local_orders: &HashMap<String, OrderInfo>, predictor: &mut AvellanedaStoikov) {
|
|
|
+ // debug!(?command);
|
|
|
+
|
|
|
+ let mut pd_amount = Decimal::ZERO;
|
|
|
+ let mut pd_order_num = 0;
|
|
|
+ let mut pk_amount = Decimal::ZERO;
|
|
|
+ let mut pk_order_num = 0;
|
|
|
+ // 各类价格
|
|
|
+ let long_upper = self.close_dist[0];
|
|
|
+ let long_lower = self.close_dist[1];
|
|
|
+ let short_lower = self.close_dist[2];
|
|
|
+ let short_upper = self.close_dist[3];
|
|
|
+
|
|
|
+ // 获取当前挂单,如果超过挂单范围则取消当前平仓单
|
|
|
+ for order_client_id in local_orders.keys() {
|
|
|
+ let order = local_orders.get(order_client_id).unwrap();
|
|
|
+ let key = format!("Cancel{}", *order_client_id);
|
|
|
+ let value = vec![order.client_id.clone(), order.order_id.clone()];
|
|
|
+
|
|
|
+ if order.side == "pk".to_string() {
|
|
|
+ if self.local_time - order.local_time > 500 || order.price > long_upper || order.price < long_lower {
|
|
|
+ command.cancel.insert(key.clone(), value.clone());
|
|
|
+ }
|
|
|
+
|
|
|
+ pk_amount += order.amount;
|
|
|
+ pk_order_num += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if order.side == "pd".to_string() {
|
|
|
+ if self.local_time - order.local_time > 500 || order.price < short_lower || order.price > short_upper {
|
|
|
+ command.cancel.insert(key.clone(), value.clone());
|
|
|
+ }
|
|
|
+
|
|
|
+ pd_amount += order.amount;
|
|
|
+ pd_order_num += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // debug!(?command);
|
|
|
+
|
|
|
+ // // 判断是否需要取消平仓订单
|
|
|
+ // let is_need_cancel_all_close =
|
|
|
+ // (pd_amount - self.pos.long_pos).abs() * self.mp > self.min_amount_value
|
|
|
+ // || (pk_amount - self.pos.short_pos).abs() * self.mp > self.min_amount_value;
|
|
|
+ // if is_need_cancel_all_close {
|
|
|
+ // for order_client_id in local_orders.keys() {
|
|
|
+ // let order = local_orders.get(order_client_id).unwrap();
|
|
|
+ //
|
|
|
+ // if order.side == "pk".to_string() || order.side == "pd".to_string() {
|
|
|
+ // let key = format!("Cancel{}", *order_client_id);
|
|
|
+ // let value = vec![order.client_id.clone(), order.order_id.clone()];
|
|
|
+ //
|
|
|
+ // command.cancel.insert(key, value);
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // // debug!(?command);
|
|
|
+
|
|
|
+ if predictor.inventory > Decimal::ZERO {
|
|
|
+ if pd_order_num == 0 {
|
|
|
+ let mut price = (short_lower + short_upper) * dec!(0.5);
|
|
|
+ // 不限制大小
|
|
|
+ // price = utils::clip(price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
|
|
|
+ price = utils::fix_price(price, self.tick_size);
|
|
|
+
|
|
|
+ let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
|
|
|
+ let order = vec![
|
|
|
+ predictor.pos_amount.abs().to_string(),
|
|
|
+ "pd".to_string(),
|
|
|
+ price.to_string(),
|
|
|
+ order_client_id.clone()
|
|
|
+ ];
|
|
|
+
|
|
|
+ command.limits_close.insert(order_client_id, order);
|
|
|
+
|
|
|
+ // debug!(?command);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if predictor.inventory < Decimal::ZERO {
|
|
|
+ if pk_order_num == 0 {
|
|
|
+ let mut price = (long_upper + long_lower) * dec!(0.5);
|
|
|
+ // 不限制大小
|
|
|
+ // price = utils::clip(price, self.bp * dec!(0.97), self.ap * dec!(1.0005));
|
|
|
+ price = utils::fix_price(price, self.tick_size);
|
|
|
+
|
|
|
+ let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
|
|
|
+ let order = vec![
|
|
|
+ predictor.pos_amount.abs().to_string(),
|
|
|
+ "pk".to_string(),
|
|
|
+ price.to_string(),
|
|
|
+ order_client_id.clone()
|
|
|
+ ];
|
|
|
+
|
|
|
+ command.limits_close.insert(order_client_id, order);
|
|
|
+
|
|
|
+ // debug!(?command);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 生成取消订单的指令
|
|
|
// #[instrument(skip(self, command), level="TRACE")]
|
|
|
pub fn _cancel_open(&self, command: &mut OrderCommand, local_orders: &HashMap<String, OrderInfo>) {
|
|
|
@@ -951,7 +1062,7 @@ impl Strategy {
|
|
|
// let one_hand_long_value = dec!(0.99) * (self.max_long_value / self.grid);
|
|
|
// let one_hand_short_value = dec!(0.99) * (self.max_short_value / self.grid);
|
|
|
// 挂多单
|
|
|
- if self.post_side >= 0 && buy_value == Decimal::ZERO && predictor.inventory <= Decimal::ZERO {
|
|
|
+ if self.post_side >= 0 && buy_value == Decimal::ZERO && predictor.inventory.is_zero() {
|
|
|
let mut target_buy_price = predictor.optimal_bid_price;
|
|
|
// target_buy_price = utils::clip(target_buy_price, self.bp * dec!(0.97), self.ap * dec!(1.0005));
|
|
|
target_buy_price = utils::fix_price(target_buy_price, self.tick_size);
|
|
|
@@ -994,7 +1105,7 @@ impl Strategy {
|
|
|
}
|
|
|
}
|
|
|
// 挂空单
|
|
|
- if self.post_side <= 0 && sell_value == Decimal::ZERO && predictor.inventory >= Decimal::ZERO {
|
|
|
+ if self.post_side <= 0 && sell_value == Decimal::ZERO && predictor.inventory.is_zero() {
|
|
|
let mut target_sell_price = predictor.optimal_ask_price;
|
|
|
// target_sell_price = utils::clip(target_sell_price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
|
|
|
// 取消大小限制
|
|
|
@@ -1116,6 +1227,7 @@ impl Strategy {
|
|
|
self.fix_price(predictor);
|
|
|
|
|
|
self._cancel_open(&mut command, local_orders); // 撤单命令处理
|
|
|
+ self._post_close(&mut command, local_orders, predictor); // 平仓单命令处理
|
|
|
self._post_open(&mut command, local_orders, predictor); // 限价单命令处理
|
|
|
self._check_local_orders(&mut command, local_orders); // 固定时间检查超时订单
|
|
|
self._update_in_cancel(&mut command, local_orders); // 更新撤单队列,是一个filter
|
|
|
@@ -1123,6 +1235,6 @@ impl Strategy {
|
|
|
self._refresh_request_limit(); // 刷新频率限制
|
|
|
self._update_request_num(&mut command); // 统计刷新频率
|
|
|
|
|
|
- return command;
|
|
|
+ command
|
|
|
}
|
|
|
}
|