Browse Source

最小下单数量加入,可以测试。

skyfffire 1 năm trước cách đây
mục cha
commit
9d7d3698ff

+ 2 - 1
standard/src/binance_swap.rs

@@ -227,6 +227,7 @@ impl Platform for BinanceSwap {
                     let filter_array = value["filters"].as_array().unwrap().clone();
                     let price_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "PRICE_FILTER").unwrap();
                     let lot_size_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "LOT_SIZE").unwrap();
+                    let min_notional_filter = filter_array.iter().find(|&item| item["filterType"].as_str().unwrap() == "MIN_NOTIONAL").unwrap();
 
                     let result = Market {
                         symbol: format!("{}_{}", base_asset, quote_asset),
@@ -238,7 +239,7 @@ impl Platform for BinanceSwap {
                         amount_precision: Decimal::from_f64(value["quantityPrecision"].as_f64().unwrap()).unwrap(),
                         min_qty: Decimal::from_str(lot_size_filter["minQty"].as_str().unwrap()).unwrap(),
                         max_qty: Decimal::from_str(lot_size_filter["maxQty"].as_str().unwrap()).unwrap(),
-                        min_notional: Decimal::from_str(price_filter["minPrice"].as_str().unwrap()).unwrap(),
+                        min_notional: Decimal::from_str(min_notional_filter["notional"].as_str().unwrap()).unwrap(),
                         max_notional: Decimal::from_str(price_filter["maxPrice"].as_str().unwrap()).unwrap(),
                         multiplier: Decimal::ONE,
                     };

+ 7 - 4
strategy/src/clear_core.rs

@@ -575,17 +575,20 @@ impl ClearCore {
         self.strategy.equity = self.strategy.start_equity.clone();
         self.strategy.total_amount = self.strategy.equity * self.strategy.lever_rate / self.strategy.mp;
         // 获取数量精度
-        self.strategy.step_size = self.market.amount_size.clone();
+        self.strategy.step_size = self.market.amount_size;
         if self.strategy.step_size > Decimal::ONE {
             self.strategy.step_size = self.strategy.step_size.trunc();
         }
         // 获取价格精度
-        self.strategy.tick_size = self.market.tick_size.clone();
+        self.strategy.tick_size = self.market.tick_size;
         if self.strategy.tick_size > Decimal::ONE {
             self.strategy.tick_size = self.strategy.tick_size.trunc();
         }
-        if self.strategy.step_size.is_zero() || self.strategy.tick_size.is_zero() {
-            self.exit_msg = format!("{}{}{}{}", "交易精度未正常获取 step_size: ", self.strategy.step_size, " tick_size:", self.strategy.tick_size);
+        // 获取最小下单价值
+        self.strategy.min_amount_value = self.market.min_notional;
+
+        if self.strategy.step_size.is_zero() || self.strategy.tick_size.is_zero() || self.strategy.min_amount_value.is_zero() {
+            self.exit_msg = format!("交易精度未正常获取 step_size:{}, tick_size:{}, min_amount_value:{}", self.strategy.step_size, self.strategy.tick_size, self.strategy.min_amount_value);
             return false;
         } else {
             info!("数量精度 {}", self.strategy.step_size);

+ 8 - 4
strategy/src/core.rs

@@ -1026,7 +1026,7 @@ impl Core {
 
         // 持仓均价异常风控(浮盈风控)
         if self.strategy.long_pos_bias != Decimal::ZERO {
-            if self.strategy.long_hold_value > Decimal::TWO * self.strategy._min_amount_value {
+            if self.strategy.long_hold_value > Decimal::TWO * self.strategy.min_amount_value {
                 if self.strategy.long_pos_bias > dec!(4) || self.strategy.long_pos_bias < -Decimal::TWO {
                     let exit_msg = format!("{} long_pos_bias: {},持仓均价异常(mp: {}, avg: {}),退出。", self.params.account_name, self.strategy.long_pos_bias, self.strategy.mp, self.strategy.pos.long_avg);
                     warn!(exit_msg);
@@ -1036,7 +1036,7 @@ impl Core {
             }
         }
         if self.strategy.short_pos_bias != Decimal::ZERO {
-            if self.strategy.short_hold_value > Decimal::TWO * self.strategy._min_amount_value {
+            if self.strategy.short_hold_value > Decimal::TWO * self.strategy.min_amount_value {
                 if self.strategy.short_pos_bias > dec!(4) || self.strategy.short_pos_bias < -Decimal::TWO {
                     let exit_msg = format!("{} short_pos_bias: {},持仓均价异常(mp: {}, avg: {}),退出。", self.params.account_name, self.strategy.short_pos_bias, self.strategy.mp, self.strategy.pos.short_avg);
                     warn!(exit_msg);
@@ -1496,14 +1496,18 @@ impl Core {
         if self.strategy.tick_size > Decimal::ONE {
             self.strategy.tick_size = self.strategy.tick_size.trunc();
         }
-        if self.strategy.step_size.is_zero() || self.strategy.tick_size.is_zero() {
-            self.exit_msg = format!("{}{}{}{}", "交易精度未正常获取 step_size: ", self.strategy.step_size, " tick_size:", self.strategy.tick_size);
+        // 获取最小下单价值
+        self.strategy.min_amount_value = self.market.min_notional;
+
+        if self.strategy.step_size.is_zero() || self.strategy.tick_size.is_zero() || self.strategy.min_amount_value.is_zero() {
+            self.exit_msg = format!("交易精度未正常获取 step_size:{}, tick_size:{}, min_amount_value:{}", self.strategy.step_size, self.strategy.tick_size, self.strategy.min_amount_value);
             // 停止程序
             self.stop().await;
             return false;
         } else {
             info!("数量精度 {}", self.strategy.step_size);
             info!("价格精度 {}", self.strategy.tick_size);
+            info!("最小下单价值 {}", self.strategy.min_amount_value);
         }
         let grid = Decimal::from(self.params.grid.clone());
         // 计算下单数量

+ 17 - 13
strategy/src/strategy.rs

@@ -63,8 +63,6 @@ pub struct Strategy {
     pub total_amount: Decimal,                                      //
     pub is_ready: bool,                                             // 程序是否已经准备好,ready
     pub _is_print: bool,                                            //
-    pub _min_amount_value: Decimal,                                 //
-    pub _max_amount_value: Decimal,                                 //
 
     pub mp_ema: Decimal,                                            // 原文的mp_ewma
     pub mp: Decimal,                                                //
@@ -75,6 +73,8 @@ pub struct Strategy {
     pub ref_ap: Decimal,                                            //
     pub step_size: Decimal,                                         // 原文的stepSize
     pub tick_size: Decimal,                                         // 原文的tickSize
+    pub min_amount_value: Decimal,                                  // 最小下单价值
+    pub max_amount_value: Decimal,                                  // 最大下单价值
 
     pub max_pos_rate: Decimal,                                      // 原文的maxPos,其实是最大持仓比例
     pub profit: Decimal,                                            //
@@ -160,8 +160,8 @@ impl Strategy {
             total_amount: Default::default(),
             is_ready: false,
             _is_print: is_print,
-            _min_amount_value: dec!(0.01),
-            _max_amount_value: dec!(10000.0),
+            min_amount_value: dec!(0.01),
+            max_amount_value: dec!(10000.0),
             mp_ema: Default::default(),
             mp: Default::default(),
             bp: Default::default(),
@@ -756,7 +756,7 @@ impl Strategy {
         // debug!(?need_close_long, ?need_close_short);
 
         // 做多仓位平仓
-        if need_close_long * self.mp > self._min_amount_value {
+        if need_close_long * self.mp > self.min_amount_value {
             let mut amount = need_close_long;
             // 现货要对数量精度进行限定处理
             if self.exchange.contains("spot") {
@@ -777,7 +777,7 @@ impl Strategy {
         }
 
         // 做空仓位平仓
-        if need_close_short * self.mp > self._min_amount_value {
+        if need_close_short * self.mp > self.min_amount_value {
             let mut amount = need_close_short;
             if self.exchange.contains("spot") {
                 amount = utils::fix_amount(amount, self.step_size);
@@ -953,16 +953,16 @@ impl Strategy {
             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);
-            let amount = utils::fix_amount(self.step_size, self.step_size);
+            let amount = utils::get_amount_by_min_amount_value(self.min_amount_value, target_buy_price, self.step_size);
             // let amount = if predictor.inventory < Decimal::ZERO {
             //     utils::fix_amount(self.step_size * predictor.inventory.abs(), self.step_size)
             // } else {
             //     utils::fix_amount(self.step_size * (predictor.level + Decimal::ONE), self.step_size)
             // };
-            let amount_value = amount * predictor.mid_price;
 
-            // 下单价值不能太大,也不能太小
-            if amount_value >= self._min_amount_value {
+            // 下单价值判定
+            let amount_value = amount * target_buy_price;
+            if amount_value >= self.min_amount_value {
                 let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
                 let order = vec![
                     amount.to_string(),
@@ -973,6 +973,8 @@ impl Strategy {
 
                 // debug!(?order);
                 command.limits_open.insert(client_id, order);
+            } else {
+                info!("下单价值太小,要求:{},但是价格:{}, 数量:{}", self.min_amount_value, target_buy_price, amount);
             }
         }
         // 挂空单, TODO 如果下单之后没有收到仓位,岂不是会连续下几单?
@@ -981,16 +983,16 @@ impl Strategy {
             // target_sell_price = utils::clip(target_sell_price, self.bp * dec!(0.9995), self.ap * dec!(1.03));
             // 取消大小限制
             target_sell_price = utils::fix_price(target_sell_price, self.tick_size);
-            let amount = utils::fix_amount(self.step_size, self.step_size);
+            let amount = utils::get_amount_by_min_amount_value(self.min_amount_value, target_sell_price, self.step_size);
             // let amount = if predictor.inventory > Decimal::ZERO {
             //     utils::fix_amount(self.step_size * predictor.inventory.abs(), self.step_size)
             // } else {
             //     utils::fix_amount(self.step_size * (predictor.level + Decimal::ONE), self.step_size)
             // };
-            let amount_value = amount * self.mp;
 
             // 下单价值不能太大,也不能太小
-            if amount_value >= self._min_amount_value {
+            let amount_value = amount * target_sell_price;
+            if amount_value >= self.min_amount_value {
                 let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
                 let order = vec![
                     amount.to_string(),
@@ -1001,6 +1003,8 @@ impl Strategy {
 
                 // debug!(?order);
                 command.limits_open.insert(client_id, order);
+            } else {
+                info!("下单价值太小,要求:{},但是价格:{}, 数量:{}", self.min_amount_value, target_sell_price, amount);
             }
         }
     }

+ 10 - 0
strategy/src/utils.rs

@@ -43,6 +43,16 @@ pub fn fix_amount(amount: Decimal, step_size: Decimal) -> Decimal {
     amount.div(step_size).floor().mul(step_size)
 }
 
+// 根据最小下单价值获取下单数量
+pub fn get_amount_by_min_amount_value(min_amount_value: Decimal,
+                                      order_price: Decimal,
+                                      step_size: Decimal) -> Decimal {
+    // ceil可以向上取整
+    let amount_unit = (min_amount_value / order_price).ceil();
+
+    amount_unit * step_size
+}
+
 // 步长修复价格
 pub fn fix_price(amount: Decimal, tick_size: Decimal) -> Decimal {
     // 思路:做除法后四舍五入,然后使用这个值乘以步长