|
|
@@ -10,7 +10,6 @@ use crate::params::Params;
|
|
|
use crate::utils;
|
|
|
use tracing::{info, trace, instrument, subscriber, debug, error};
|
|
|
use tracing_subscriber;
|
|
|
-use tracing_subscriber::fmt::format;
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
pub struct Strategy {
|
|
|
@@ -503,7 +502,147 @@ impl Strategy {
|
|
|
|
|
|
// 平仓订单处理命令
|
|
|
#[instrument(skip(self, command), level="TRACE")]
|
|
|
- pub fn _post_close(&self, command: &OrderCommand) {
|
|
|
+ pub fn _post_close(&self, command: &mut OrderCommand) {
|
|
|
+ trace!(?command);
|
|
|
+
|
|
|
+ let mut pd_amount = dec!(0);
|
|
|
+ let mut pd_order_num = 0;
|
|
|
+ let mut pk_amount = dec!(0);
|
|
|
+ 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 self.local_orders.keys() {
|
|
|
+ let order = self.local_orders.get(order_client_id).unwrap();
|
|
|
+ let key = format!("Cancel{}", (*order_client_id).clone());
|
|
|
+ let value = vec![order.client_id.clone(), order.order_id.clone()];
|
|
|
+
|
|
|
+ if order.side == "pk".to_string() {
|
|
|
+ if 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 order.price < short_lower || order.price > short_upper {
|
|
|
+ command.cancel.insert(key.clone(), value.clone());
|
|
|
+ }
|
|
|
+
|
|
|
+ pd_amount += order.amount;
|
|
|
+ pd_order_num += 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ trace!(?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 self.local_orders.keys() {
|
|
|
+ let order = self.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).clone());
|
|
|
+ let value = vec![order.client_id.clone(), order.order_id.clone()];
|
|
|
+
|
|
|
+ command.cancel.insert(key.clone(), value.clone());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ trace!(?command);
|
|
|
+
|
|
|
+ // 区分现货和期货
|
|
|
+ if self.exchange.contains("spot") {
|
|
|
+ // 平多价值大于最小交易价值,执行平多逻辑
|
|
|
+ if self.pos.long_pos * self.mp > self._min_amount_value {
|
|
|
+ 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 mut amount = self.pos.long_pos;
|
|
|
+ amount = utils::fix_amount(amount, self.step_size);
|
|
|
+
|
|
|
+ if amount * price > self._min_amount_value {
|
|
|
+ let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
|
|
|
+ let order = vec![
|
|
|
+ amount.to_string(),
|
|
|
+ "pd".to_string(),
|
|
|
+ price.to_string(),
|
|
|
+ order_client_id.clone()
|
|
|
+ ];
|
|
|
+ command.limits_open.insert(order_client_id, order.clone());
|
|
|
+
|
|
|
+ trace!(?command);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 平空价值大于最小交易价值,执行平空逻辑
|
|
|
+ if self.pos.short_pos > self._min_amount_value {
|
|
|
+ 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 mut amount = self.pos.short_pos;
|
|
|
+ amount = utils::fix_amount(amount, self.step_size);
|
|
|
+
|
|
|
+ if amount * price > self._min_amount_value {
|
|
|
+ let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
|
|
|
+ let order = vec![
|
|
|
+ amount.to_string(),
|
|
|
+ "pk".to_string(),
|
|
|
+ price.to_string(),
|
|
|
+ order_client_id.clone()
|
|
|
+ ];
|
|
|
+ command.limits_open.insert(order_client_id, order.clone());
|
|
|
+
|
|
|
+ trace!(?command);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if self.pos.long_pos > dec!(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![
|
|
|
+ self.pos.long_pos.to_string(),
|
|
|
+ "pd".to_string(),
|
|
|
+ price.to_string(),
|
|
|
+ order_client_id.clone()
|
|
|
+ ];
|
|
|
+
|
|
|
+ command.limits_open.insert(order_client_id, order.clone());
|
|
|
+
|
|
|
+ trace!(?command);
|
|
|
+ }
|
|
|
+
|
|
|
+ if self.pos.short_pos > dec!(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![
|
|
|
+ self.pos.short_pos.to_string(),
|
|
|
+ "pk".to_string(),
|
|
|
+ price.to_string(),
|
|
|
+ order_client_id.clone()
|
|
|
+ ];
|
|
|
+
|
|
|
+ trace!(?command);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 生成取消订单的指令
|
|
|
@@ -590,7 +729,7 @@ impl Strategy {
|
|
|
let mut short_free_value = self.max_short_value - self.short_hold_value - sell_value;
|
|
|
trace!(?long_free_value, ?short_free_value);
|
|
|
// 现货要特殊处理
|
|
|
- if self.exchange.contains(&"spot") {
|
|
|
+ if self.exchange.contains("spot") {
|
|
|
let coin_value = self.coin * self.mp * self.lever_rate * self.adjust_lever_rate;
|
|
|
let cash_value = self.cash * self.lever_rate * self.adjust_lever_rate;
|
|
|
|
|
|
@@ -601,8 +740,10 @@ 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);
|
|
|
|
|
|
+ trace!(?self.post_side);
|
|
|
// 挂多单
|
|
|
if self.post_side >= 0 {
|
|
|
+ trace!(?buy_price_list);
|
|
|
if buy_price_list.len() == 0 {
|
|
|
let mut target_buy_price = (long_upper + long_lower) * dec!(0.5);
|
|
|
target_buy_price = utils::clip(target_buy_price, self.bp * dec!(0.97), self.ap * dec!(1.0005));
|
|
|
@@ -631,6 +772,7 @@ impl Strategy {
|
|
|
}
|
|
|
// 挂空单
|
|
|
if self.post_side <= 0 {
|
|
|
+ trace!(?sell_price_list);
|
|
|
if sell_price_list.len() == 0 {
|
|
|
let mut target_sell_price = (short_lower + short_upper) * dec!(0.5);
|
|
|
target_sell_price = utils::clip(target_sell_price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
|
|
|
@@ -703,7 +845,6 @@ impl Strategy {
|
|
|
// 下单指令处理逻辑
|
|
|
self._cancel_open(&mut command); // 撤单命令处理
|
|
|
self._post_open(&mut command); // 限价单命令处理
|
|
|
- // TODO 平仓单处理命令
|
|
|
self._post_close(&mut command); // 平仓单命令处理
|
|
|
self._check_local_orders(&mut command); // 固定时间检查超时订单
|
|
|
self._update_in_cancel(&mut command); // 更新撤单队列,是一个filter
|
|
|
@@ -734,7 +875,7 @@ mod tests {
|
|
|
trader_msg.orders.insert("0001".to_string(), OrderInfo{
|
|
|
symbol: "".to_string(),
|
|
|
amount: Default::default(),
|
|
|
- side: "kk".to_string(),
|
|
|
+ side: "pd".to_string(),
|
|
|
price: dec!(10),
|
|
|
client_id: "0001".to_string(),
|
|
|
filled_price: Default::default(),
|