浏览代码

v4.2.0_beta: 可以编译通过的版本,还没测试运行!

skyffire 8 月之前
父节点
当前提交
1910f0df05
共有 8 个文件被更改,包括 221 次插入222 次删除
  1. 1 1
      Cargo.toml
  2. 5 8
      global/src/params.rs
  3. 5 0
      src/main.rs
  4. 2 2
      standard/src/bitget_swap.rs
  5. 2 2
      standard/src/bybit_swap.rs
  6. 49 29
      strategy/src/core.rs
  7. 140 159
      strategy/src/predictor.rs
  8. 17 21
      strategy/src/strategy.rs

+ 1 - 1
Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "as-rust"
-version = "4.1.1"
+version = "4.2.0"
 edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

+ 5 - 8
global/src/params.rs

@@ -24,10 +24,6 @@ pub struct Params {
     pub pair: String,
     // 开仓
     pub open: Decimal,
-    // 最小挂单值
-    pub min_open: Decimal,
-    // 激活平仓挂单
-    pub close_activate: Decimal,
     // 平仓
     pub close: Decimal,
     // 杠杆大小
@@ -47,7 +43,9 @@ pub struct Params {
     // 平滑系数 默认0.999
     pub gamma: Decimal,
     // 分批建仓功能 小资金建议1 大资金建议3 默认 1
-    pub grid: i8,
+    pub grid: Decimal,
+    // 持仓时间(秒)
+    pub holding_time: Decimal,
     // 是否启用colocation技术, 1开启,0关闭 默认0
     pub colo: i8,
     // 日志级别,从低到高依次是:[trace, debug, info, warn, error]
@@ -89,16 +87,15 @@ impl Params {
             exchange: json_value["exchange"].as_str().unwrap().to_string(),
             pair: json_value["pair"].as_str().unwrap().to_string(),
             open: Decimal::try_from(json_value["open"].as_f64().unwrap_or_default()).unwrap(),
-            min_open: Decimal::try_from(json_value["min_open"].as_f64().unwrap()).unwrap(),
             close: Decimal::try_from(json_value["close"].as_f64().unwrap_or_default()).unwrap(),
             lever_rate: Decimal::try_from(json_value["lever_rate"].as_f64().unwrap_or_default()).unwrap(),
             ref_exchange: serde_json::from_str(json_value["ref_exchanges"].clone().as_str().unwrap()).unwrap(),
             ref_pair: serde_json::from_str(json_value["ref_pairs"].clone().as_str().unwrap()).unwrap(),
             stop_loss: Decimal::try_from(json_value["stop_loss"].as_f64().unwrap_or_default()).unwrap(),
             // 接下来是写死的参数
-            close_activate: Decimal::ZERO,
             hold_coin: Decimal::ZERO,
-            grid: 1,
+            grid: Decimal::try_from(json_value["grid"].as_f64().unwrap_or_default()).unwrap(),
+            holding_time: Decimal::try_from(json_value["holding_time"].as_f64().unwrap_or_default()).unwrap(),
             colo: 0,
             interval: 100,
             broker_id: json_value["exchange"].as_str().unwrap().to_string().split("_").collect::<Vec<_>>()[0].to_string(),

+ 5 - 0
src/main.rs

@@ -8,6 +8,7 @@ use std::sync::Arc;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::time::Duration;
 use backtrace::Backtrace;
+use rust_decimal::Decimal;
 use tokio::sync::Mutex;
 use tracing::{error, info, warn};
 use tracing_appender_timezone::non_blocking::WorkerGuard;
@@ -129,6 +130,10 @@ async fn main() {
         _guard = log_level_init(params.log_level.clone(), params.port.clone());
     }
 
+    if params.grid < Decimal::ONE {
+        info!("分批建仓要大于0。你的值:{}。", params.grid);
+    }
+
     info!("--------------------------------程序开始执行-----------------------------");
     info!("配置读取成功:{:?}。", params);
     // 主进程控制

+ 2 - 2
standard/src/bitget_swap.rs

@@ -471,7 +471,7 @@ impl Platform for BitgetSwap {
             }
             "pd" => {
                 params["side"] = json!("sell");
-                params["reduceOnly"] = json!("YES");
+                // params["reduceOnly"] = json!("YES");
             }
             "kk" => {
                 params["side"] = json!("sell");
@@ -479,7 +479,7 @@ impl Platform for BitgetSwap {
             }
             "pk" => {
                 params["side"] = json!("buy");
-                params["reduceOnly"] = json!("YES");
+                // params["reduceOnly"] = json!("YES");
             }
             _ => { panic!("bitget_usdt_swap 下单参数错误"); }
         };

+ 2 - 2
standard/src/bybit_swap.rs

@@ -413,7 +413,7 @@ impl Platform for BybitSwap {
             "pd" => {
                 params["side"] = json!("Sell");
                 // 减仓
-                params["reduceOnly"] = json!(true);
+                // params["reduceOnly"] = json!(true);
             }
             "kk" => {
                 params["side"] = json!("Sell");
@@ -422,7 +422,7 @@ impl Platform for BybitSwap {
             "pk" => {
                 params["side"] = json!("Buy");
                 // 减仓
-                params["reduceOnly"] = json!(true);
+                // params["reduceOnly"] = json!(true);
                 // params["positionIdx"] = json!(2);
             }
             _ => { error!("下单参数错误"); }

+ 49 - 29
strategy/src/core.rs

@@ -388,7 +388,7 @@ impl Core {
                                 self.local_cash -= filled * filled_price;
                                 self.local_coin = filled - fee;
 
-                                // sell 平多
+                            // sell 平多
                             } else if side == "pd" {
                                 self.local_sell_amount += filled;
                                 self.local_sell_value += filled * filled_price;
@@ -453,6 +453,8 @@ impl Core {
                                     self.local_position_by_orders.long_pos = self.local_position_by_orders.long_pos + filled;
                                 }
 
+                                self.predictor.on_order(side, filled).await
+
                             // sell 开空
                             } else if side == "kk" {
                                 self.local_sell_amount += filled;
@@ -466,6 +468,8 @@ impl Core {
                                     self.local_position_by_orders.short_pos = self.local_position_by_orders.short_pos + filled;
                                 }
 
+                                self.predictor.on_order(side, filled).await
+
                             // sell 平多
                             } else if side == "pd" {
                                 self.local_sell_amount += filled;
@@ -475,6 +479,8 @@ impl Core {
                                     self.local_position_by_orders.long_avg = Decimal::ZERO;
                                 }
 
+                                self.predictor.on_order(side, filled).await
+
                             // buy 平空
                             } else if side == "pk" {
                                 self.local_buy_amount += filled;
@@ -483,6 +489,8 @@ impl Core {
                                 if self.local_position_by_orders.short_pos == Decimal::ZERO {
                                     self.local_position_by_orders.short_avg = Decimal::ZERO;
                                 }
+
+                                self.predictor.on_order(side, filled).await
                             } else {
                                 error!("错误的仓位方向{}", side);
                             }
@@ -493,6 +501,12 @@ impl Core {
                         }
                         // info!("成交单耗时数据:{}", time_record.to_string());
                         info!("更新推算仓位 {:?}", self.local_position_by_orders);
+
+                        // 有的交易所空仓后半天不推仓位……
+                        if self.local_position_by_orders.short_pos == self.local_position_by_orders.long_pos {
+                            self.predictor.on_inventory(&Decimal::ZERO, &Decimal::ZERO, &self.strategy.min_amount_value, Decimal::from(filled_order.local_time)).await;
+                        }
+
                         let place_time = self.local_order_infos.get(&data.client_id).unwrap()[4].parse::<i64>().unwrap();
                         info!("当前时间-订单委托时间={}ms, cid={}", Utc::now().timestamp_millis() - place_time, data.client_id.clone());
                         if let Some(oi) = self.local_cancel_cache.get(&data.client_id) {
@@ -727,9 +741,15 @@ impl Core {
             let mut now_price = self.strategy.mp;
             now_price.rescale(8);
 
+            let mut now_balance = (self.local_cash + self.local_coin * self.predictor.mid_price) / self.used_pct;
+            now_balance.rescale(4);
+
             let mut cci = self.cci_arc.lock().await;
             cci.unrealized_pn_l = unrealized_pn_l;
             cci.now_price = now_price;
+            cci.now_balance = now_balance;
+
+            self.predictor.on_balance(now_balance).await;
         }
     }
 
@@ -1103,27 +1123,27 @@ 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_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);
-                    self.exit_msg = exit_msg;
-                    self.stop().await;
-                }
-            }
-        }
-        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_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);
-                    self.exit_msg = exit_msg;
-                    self.stop().await;
-                }
-            }
-        }
+        // // 持仓均价异常风控(浮盈风控)
+        // 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_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);
+        //             self.exit_msg = exit_msg;
+        //             self.stop().await;
+        //         }
+        //     }
+        // }
+        // 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_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);
+        //             self.exit_msg = exit_msg;
+        //             self.stop().await;
+        //         }
+        //     }
+        // }
 
         // 订单撤单异常风控
         for (client_id, cancel_delay) in self.local_cancel_log.clone() {
@@ -1137,13 +1157,13 @@ impl Core {
         }
 
         // 定价异常风控
-        // if self.ready == 1 && (self.predictor.fair_price - self.predictor.mid_price).abs() / self.predictor.mid_price > dec!(0.03) {
-        //     let exit_msg = format!("{} 定价偏离过大,怀疑定价异常,退出。", self.params.account_name);
-        //     warn!(exit_msg);
-        //     warn!(?self.predictor.fair_price, ?self.predictor.mid_price);
-        //     self.exit_msg = exit_msg;
-        //     self.stop().await;
-        // }
+        if self.ready == 1 && (self.predictor.fair_price - self.predictor.mid_price).abs() / self.predictor.mid_price > dec!(0.03) {
+            let exit_msg = format!("{} 定价偏离过大,怀疑定价异常,退出。", self.params.account_name);
+            warn!(exit_msg);
+            warn!(?self.predictor.fair_price, ?self.predictor.mid_price);
+            self.exit_msg = exit_msg;
+            self.stop().await;
+        }
     }
 
     // #[instrument(skip(self), level="TRACE")]

+ 140 - 159
strategy/src/predictor.rs

@@ -1,5 +1,4 @@
-use std::cmp::{max, min};
-use std::collections::{BTreeMap, VecDeque};
+use std::collections::{BTreeMap, HashMap, VecDeque};
 use std::sync::Arc;
 use chrono::{Utc};
 use futures_channel::mpsc::UnboundedSender;
@@ -16,10 +15,7 @@ use crate::utils;
 
 #[derive(Debug, Clone)]
 pub struct Predictor {
-    pub depth_vec: Vec<Depth>,                                                  // 深度队列
-    pub record_vec: VecDeque<Record>,                                           // 蜡烛队列
-
-    // 做市所的计算
+    // MeanReversion概率相关
     pub close_price_vec: FixedTimeRangeDeque<Record>,
     pub log_return_vec: VecDeque<Decimal>,
     pub r_vec: VecDeque<Decimal>,
@@ -29,68 +25,67 @@ pub struct Predictor {
     pub phi: Decimal,
     pub weights: VecDeque<Decimal>,
 
-    pub prices: Vec<Vec<FixedTimeRangeDeque<Decimal>>>,                         // [[[做市所], [参考所0]], ...]
-    pub ks: Vec<Decimal>,
-    pub bs: Vec<Decimal>,
-
+    // 价格相关
     pub mid_price: Decimal,                                                     // 中间价
-    pub ask_price: Decimal,                                                     // 中间价
-    pub bid_price: Decimal,                                                     // 中间价
-    pub fair_price: Decimal,
+    pub ask_price: Decimal,                                                     // a1
+    pub bid_price: Decimal,                                                     // b1
+    pub fair_price: Decimal,                                                    // 公平价
     pub last_price: Decimal,                                                    // 最后成交价
+    pub depth_vec: Vec<Depth>,                                                  // 深度队列
 
-    pub optimal_ask_price: Decimal,                                             // 卖出挂单价
-    pub optimal_bid_price: Decimal,                                             // 买入挂单价
-
+    // 库存相关
     pub inventory: Decimal,                                                     // 库存,也就是q
     pub pos_amount: Decimal,                                                    // 原始持仓量
     pub pos_avg_price: Decimal,                                                 // 原始持仓价格
     pub balance: Decimal,                                                       // 初始余额
-    pub prev_balance: Decimal,
+    pub one_grid_order_value: Decimal,                                          // 每一网格下单价值
     pub profit: Decimal,
-    pub profit_high: Decimal,
+    pub profit_high: Decimal,                                                   // 总体持仓利润的最大值
 
-    pub prev_open_time: Decimal,
-
-    pub trade_condition: Decimal,                                               // 交易信号
+    // 交易信号相关
+    pub trade_condition: Decimal,                                               // 交易信号,用于保存一段时间的交易信号
     pub trade_condition_time: Decimal,                                          // 满足时的瞬时时间,用于控制开仓行为的持续时间
-
     pub ask_delta: Decimal,                                                     // δa
     pub bid_delta: Decimal,                                                     // δb
+    pub optimal_ask_price: Decimal,                                             // 卖出挂单价
+    pub optimal_bid_price: Decimal,                                             // 买入挂单价
 
+    // 公平价生成相关
+    pub prev_fitting_time_vec: Vec<Decimal>,                                    // 生成公平价的时间
     pub mid_price_vec: Vec<Decimal>,                                            // 每个交易所的中间价
     pub fair_price_std_vec: Vec<Decimal>,                                       // 公平价格列表,标准化之后的
-    pub price_avg_times_vec: Vec<Decimal>,                                      // 公平所与做市所的价格倍率的平均值
-    pub price_avg_times_long_vec: Vec<Decimal>,                                 // 公平所与做市所的价格倍率的平均值
-
-    pub is_ready: bool,                                                         // 是否已准备好
-
-    pub last_update_time: Decimal,                                              // 最后更新时间(depth)
-    pub last_index: Decimal,                                                    // 最后更新的index
+    pub prices: Vec<Vec<FixedTimeRangeDeque<Decimal>>>,                         // [[[做市所], [参考所0]], ...]
+    pub ks: Vec<Decimal>,                                                       // 拟合的斜率
+    pub bs: Vec<Decimal>,                                                       // 拟合的截距
 
-    pub prev_insert_time: Decimal,
-    pub prev_save_time: Decimal,
-    pub init_time: Decimal,
-    pub fitting_delay: Decimal,
-    pub prev_fitting_time_vec: Vec<Decimal>,
+    // 网格开平仓相关
+    pub trade_time_vec: VecDeque<Decimal>,                                      // 成交时间队列
+    pub trade_side_map: HashMap<Decimal, String>,                               // 成交时间对应的是kk,kd两个方向
+    pub trade_amount_map: HashMap<Decimal, Decimal>,                            // 成交对应的交易数量
+    pub ready_close_amount: Decimal,                                            // 预计平仓数量
 
+    // 系统相关变量
+    pub is_ready: bool,                                                         // 是否已准备好
     pub params: Params,
 
-    pub debug_sender: UnboundedSender<Vec<Decimal>>
+    // 马尔可夫链相关
+    // pub prev_update_state_time: Decimal,
+    // pub state: usize,
+    // pub state_matrix: Vec<Vec<Decimal>>,
+
+    // debug、图表相关
+    pub debug_sender: UnboundedSender<Vec<Decimal>>,
+    pub prev_plot_time: Decimal,
 }
 
 impl Predictor {
-    // 时间窗口大小(微秒)
-    // const MAX_TIME_RANGE_MICROS: i64 = 3 * 60_000_000;
-    // const TIME_DIFF_RANGE_MICROS: i64 = 15 * 60_000_000;
-    // const TRADE_LONG_RANGE_MICROS: i64 = 10 * 60_000_000;
-    // const SPREAD_RANGE_MICROS: i64 = 15 * 60_000_000;
-    // const TRADE_SHORT_RANGE_MICROS: i64 = 10_000_000;
-    // const ONE_MILLION: Decimal = dec!(1_000_000);
-    // const TWENTY_THOUSAND: Decimal = dec!(20_000);
     const DONT_VIEW: Decimal = dec!(14142135623730951);
 
     pub fn new(_cci_arc: Arc<Mutex<CentralControlInfo>>, params: Params) -> Self {
+        if params.close.is_zero() {
+            panic!("做市策略特殊逻辑要求平仓距离不得为0。");
+        }
+
         // 创建数据通道
         // 创建一个无界通道
         let (tx, mut rx) = futures_channel::mpsc::unbounded::<Vec<Decimal>>();
@@ -149,12 +144,9 @@ impl Predictor {
         });
 
         let predictor = Self {
-            // 接针版本
             depth_vec: vec![Depth::new(); params.ref_exchange.len()],
             fair_price_std_vec: vec![Decimal::ZERO; params.ref_exchange.len()],
             mid_price_vec: vec![Decimal::ZERO; params.ref_exchange.len()],
-            price_avg_times_vec: vec![Decimal::ZERO; params.ref_exchange.len()],
-            price_avg_times_long_vec: vec![Decimal::ZERO; params.ref_exchange.len()],
 
             prices: vec![vec![FixedTimeRangeDeque::new(600_000_000); 2]; params.ref_exchange.len()],
             ks: vec![Decimal::ZERO; params.ref_exchange.len()],
@@ -188,37 +180,37 @@ impl Predictor {
             pos_avg_price: Default::default(),
             pos_amount: Default::default(),
             balance: Default::default(),
-            prev_balance: Default::default(),
 
+            one_grid_order_value: Default::default(),
             profit: Default::default(),
             profit_high: Default::default(),
 
             trade_condition: Default::default(),
             trade_condition_time: Default::default(),
 
-            last_update_time: Default::default(),
-            last_index: Default::default(),
-
-            prev_insert_time: Default::default(),
-            prev_save_time: Decimal::from(Utc::now().timestamp_millis()),
-            init_time: Decimal::from(Utc::now().timestamp_millis()),
-
-            fitting_delay: Default::default(),
+            prev_plot_time: Default::default(),
             params,
 
             debug_sender: tx,
-            prev_open_time: Default::default(),
 
-            record_vec: Default::default(),
+            trade_time_vec: VecDeque::new(),
+            trade_side_map: HashMap::new(),
+            trade_amount_map: HashMap::new(),
+            ready_close_amount: Default::default(),
+
+            // prev_update_state_time: Default::default(),
+            // state: 1,
+            // state_matrix: vec![
+            //     vec![dec!(0.33), dec!(0.33), dec!(0.33)],
+            //     vec![dec!(0.33), dec!(0.33), dec!(0.33)],
+            //     vec![dec!(0.33), dec!(0.33), dec!(0.33)],
+            // ],
         };
 
         predictor
     }
 
     pub async fn on_depth(&mut self, depth: &Depth, index: usize) {
-        self.last_update_time = depth.time;
-        self.last_index = Decimal::from(index);
-
         if index == 233  {
             self.ask_price = depth.asks[0].price;
             self.bid_price = depth.bids[0].price;
@@ -319,7 +311,6 @@ impl Predictor {
                         self.ks[mid_index] = k;
                         self.bs[mid_index] = b;
 
-                        self.fitting_delay = Decimal::from(Utc::now().timestamp_millis() - before_fitting);
                         self.prev_fitting_time_vec[mid_index] = Decimal::from(before_fitting)
                     } else {
                         return;
@@ -347,66 +338,64 @@ impl Predictor {
         self.last_price = trade.price;
     }
 
-    pub async fn on_ticker(&mut self, _ticker: &Ticker) {}
+    // side, pk,pd从HashMap移除,kd,kk添加到HashMap
+    pub async fn on_order(&mut self, side: String, amount: Decimal) {
+        self.inventory = match side.as_str() {
+            "kk" => {
+                self.inventory - Decimal::ONE
+            }
+            "pd" => {
+                self.inventory - Decimal::ONE
+            }
+            "kd" => {
+                self.inventory + Decimal::ONE
+            }
+            "pk" => {
+                self.inventory + Decimal::ONE
+            }
+            &_ => {
+                panic!("不认识的order方向:{}", side);
+            }
+        };
 
-    pub async fn on_record(&mut self, record: &Record) {
-        // 添加新蜡烛
-        if self.record_vec.len() == 0 {
-            self.record_vec.push_back(record.clone());
-        } else {
-            let last_record = self.record_vec.back_mut().unwrap();
+        if side == "kk" || side == "kd" {
+            let now = Decimal::from(Utc::now().timestamp_millis());
 
-            if last_record.time == record.time {
-                *last_record = record.clone();
-            } else if last_record.time < record.time {
-                self.record_vec.push_back(record.clone());
-            }
+            self.trade_time_vec.push_back(now);
+            self.trade_side_map.insert(now, side);
+            self.trade_amount_map.insert(now, amount);
+        } else if side == "pd" || side == "pk" {
+            let pop_time = self.trade_time_vec.pop_front().unwrap();
+
+            self.trade_side_map.remove(&pop_time);
+            self.trade_amount_map.remove(&pop_time);
         }
 
-        if self.record_vec.len() > 5 {
-            self.record_vec.pop_front();
+        info!(?self.trade_time_vec);
+        info!(?self.trade_side_map);
+        info!(?self.trade_amount_map);
+    }
+
+    pub async fn on_ticker(&mut self, _ticker: &Ticker) {}
+
+    pub async fn on_record(&mut self, _record: &Record) {}
+
+    pub async fn on_balance(&mut self, balance: Decimal) {
+        self.balance = balance;
+        if self.inventory.is_zero() {
+            self.one_grid_order_value = (self.params.lever_rate * self.balance) / self.params.grid;
         }
     }
 
-    pub async fn on_inventory(&mut self, pos_amount: &Decimal, pos_avg_price: &Decimal, min_amount_value: &Decimal, update_time: Decimal) {
+    pub async fn on_inventory(&mut self, pos_amount: &Decimal, pos_avg_price: &Decimal, _min_amount_value: &Decimal, update_time: Decimal) {
         if self.mid_price.is_zero() {
             return;
         }
 
-        let prev_pos_amount = self.pos_amount;
         self.pos_amount = pos_amount.clone();
         self.pos_avg_price = pos_avg_price.clone();
-        self.inventory = (pos_amount / (min_amount_value / self.mid_price)).trunc();
-        // 小于1但不为0的情况,需要平完
-        if self.inventory.is_zero() && !pos_amount.is_zero() {
-            self.inventory = if pos_amount > &Decimal::ZERO {
-                Decimal::ONE
-            } else {
-                Decimal::NEGATIVE_ONE
-            };
-        }
-
-        if prev_pos_amount != self.pos_amount {
-            // 重置连续信号
-            self.trade_condition = Decimal::ZERO;
-            self.trade_condition_time = Decimal::ZERO;
-
-            // 开仓
-            if prev_pos_amount.is_zero() {
-                self.prev_open_time = Decimal::from(Utc::now().timestamp_millis())
-            }
-            // 平仓
-            if self.pos_amount.is_zero() {
-                self.profit = Decimal::ZERO;
-                self.profit_high = Decimal::ZERO;
-            }
-
-            self.processor(update_time, true).await;
-        }
-    }
 
-    pub async fn on_balance(&mut self, balance: Decimal) {
-        self.balance = balance;
+        self.processor(update_time, true).await;
     }
 
     pub async fn update_fair_price(&mut self, latest_price: &Decimal, index: usize) {
@@ -414,11 +403,6 @@ impl Predictor {
             return;
         }
 
-        // https://quant.stackexchange.com/questions/50651/how-to-understand-micro-price-aka-weighted-mid-price
-        // let total = a1.value + b1.value;
-        // let fair_price = (a1.price + b1.price) / Decimal::TWO;
-
-        // self.fair_price_vec[index] = a1.price * b1.value / total + b1.price * a1.value / total;
         let mut mp = latest_price.clone();
         mp.rescale(self.mid_price.scale());
         self.mid_price_vec[index] = mp;
@@ -438,18 +422,6 @@ impl Predictor {
             } else {
                 dec!(0.9) * self.fair_price + dec!(0.1) * fair_price_sum / Decimal::from(fair_price_count)
             };
-
-            // let mut spread_abs = ((self.fair_price - self.mid_price) / self.mid_price).abs();
-            // spread_abs.rescale(5);
-            //
-            // self.spread_vec.push_back(spread_abs);
-            // if self.spread_vec.len() > 3000 {
-            //     self.spread_vec.pop_front();
-            // }
-            //
-            // let opt_abs_value = self.spread_vec.iter().max().unwrap().clone();
-            //
-            // self.params.open = max(max(self.params.min_open, dec!(0.0006)), opt_abs_value);
         }
     }
 
@@ -458,18 +430,31 @@ impl Predictor {
             return false;
         }
 
-        let prev_bid_delta = self.bid_delta;
-        let prev_ask_delta = self.ask_delta;
-
         let now = Decimal::from(Utc::now().timestamp_millis());
+        // 平仓优先级高一些
+        if self.trade_time_vec.len() > 0 {
+            let first = self.trade_time_vec.front().unwrap();
 
-        let is_close_long = self.inventory > Decimal::ZERO && (
-            // 硬止损,开单不久之后就在亏
-            (self.profit_high < dec!(0.001) && self.profit < dec!(-0.01))
-            // 时间到了,追踪止盈
-            || (now - self.prev_open_time > dec!(100_000) && self.profit < self.profit_high * dec!(0.75))
-        );
-        let is_close_short = self.inventory < Decimal::ZERO;
+            if now - *first > self.params.holding_time * Decimal::ONE_THOUSAND {
+                let side = self.trade_side_map.get(first).unwrap();
+                self.ready_close_amount = self.trade_amount_map.get(first).unwrap().clone();
+
+                match side.as_str() {
+                    "kd" => {
+                        self.ask_delta = self.mid_price * self.params.close;
+                    }
+                    "kk" => {
+                        self.bid_delta = self.mid_price * self.params.close;
+                    }
+                    &_ => {
+                        panic!("什么方向放进来了?side={}", side);
+                    }
+                }
+            }
+        }
+
+        let prev_bid_delta = self.bid_delta;
+        let prev_ask_delta = self.ask_delta;
 
         let is_open_long = self.inventory.is_zero()
             && self.phi > Decimal::ONE
@@ -481,12 +466,6 @@ impl Predictor {
         ;
 
         // 使信号有一定持续性
-        if is_close_long {
-            self.trade_condition = dec!(1);
-        }
-        if is_close_short {
-            self.trade_condition = dec!(2);
-        }
         if is_open_long {
             self.trade_condition = dec!(3);
             self.trade_condition_time = now;
@@ -496,9 +475,9 @@ impl Predictor {
             self.trade_condition_time = now;
         }
 
-        // 开仓信号要过期,只保留2
+        // 开仓信号要过期,只保留60
         if (self.trade_condition == dec!(3) || self.trade_condition == dec!(4))
-            && now - self.trade_condition_time > dec!(2_000) {
+            && now - self.trade_condition_time > dec!(60_000) {
             self.trade_condition = Decimal::ZERO;
         }
 
@@ -508,29 +487,31 @@ impl Predictor {
         self.optimal_ask_price = Self::DONT_VIEW;
         self.optimal_bid_price = Self::DONT_VIEW;
 
-        if self.trade_condition == dec!(1) && self.inventory > Decimal::ZERO {
-            self.ask_delta = dec!(0);
-            self.bid_delta = dec!(-2);
-
-            self.optimal_ask_price = min(self.fair_price, self.mid_price) * dec!(0.995);
-            self.optimal_bid_price = Self::DONT_VIEW;
-        } else if self.trade_condition == dec!(2) && self.inventory < Decimal::ZERO {
-            self.bid_delta = dec!(0);
-            self.ask_delta = dec!(-2);
-
-            self.optimal_bid_price = max(self.fair_price, self.mid_price) * dec!(1.005);
-            self.optimal_ask_price = Self::DONT_VIEW;
-        } else if self.trade_condition == dec!(3) {
+        // if self.trade_condition == dec!(1) && self.inventory > Decimal::ZERO {
+        //     self.ask_delta = dec!(0);
+        //     self.bid_delta = dec!(-2);
+        //
+        //     self.optimal_ask_price = min(self.fair_price, self.mid_price) * dec!(0.995);
+        //     self.optimal_bid_price = Self::DONT_VIEW;
+        // } else if self.trade_condition == dec!(2) && self.inventory < Decimal::ZERO {
+        //     self.bid_delta = dec!(0);
+        //     self.ask_delta = dec!(-2);
+        //
+        //     self.optimal_bid_price = max(self.fair_price, self.mid_price) * dec!(1.005);
+        //     self.optimal_ask_price = Self::DONT_VIEW;
+        // } else
+
+        if self.trade_condition == dec!(3) {
             self.bid_delta = dec!(0);
             self.ask_delta = dec!(-2);
 
-            self.optimal_bid_price = max(self.fair_price, self.mid_price) * dec!(1.005);
+            self.optimal_bid_price = self.mid_price;
             self.optimal_ask_price = Self::DONT_VIEW;
         } else if self.trade_condition == dec!(4) {
             self.ask_delta = dec!(0);
             self.bid_delta = dec!(-2);
 
-            self.optimal_ask_price = min(self.fair_price, self.mid_price) * dec!(0.995);
+            self.optimal_ask_price = self.mid_price;
             self.optimal_bid_price = Self::DONT_VIEW;
         }
 
@@ -774,12 +755,12 @@ impl Predictor {
 
         let flow_ratio = Decimal::ZERO;
 
-        let is_time_over_update = now - self.prev_insert_time > dec!(500);
+        let is_time_over_update = now - self.prev_plot_time > dec!(500);
         if !is_time_over_update && !is_hard_update && !is_delta_changed {
             return;
         }
         if is_time_over_update {
-            self.prev_insert_time = Decimal::from(Utc::now().timestamp_millis())
+            self.prev_plot_time = Decimal::from(Utc::now().timestamp_millis())
         }
         let pos_avg_price = self.pos_avg_price;
 

+ 17 - 21
strategy/src/strategy.rs

@@ -813,7 +813,7 @@ impl Strategy {
         // }
         // // debug!(?command);
 
-        if predictor.inventory > Decimal::ZERO && predictor.ask_delta != dec!(-2) {
+        if predictor.ask_delta != dec!(-2) && predictor.ask_delta != Decimal::ZERO {
             if pd_order_num == 0 {
                 let mut price = (short_lower + short_upper) * dec!(0.5);
                 // 不限制大小
@@ -822,7 +822,7 @@ impl Strategy {
 
                 let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
                 let order = vec![
-                    predictor.pos_amount.abs().to_string(),
+                    predictor.ready_close_amount.to_string(),
                     "pd".to_string(),
                     price.to_string(),
                     order_client_id.clone(),
@@ -837,7 +837,7 @@ impl Strategy {
                 // debug!(?command);
             }
         }
-        if predictor.inventory < Decimal::ZERO && predictor.bid_delta != dec!(-2) {
+        if predictor.bid_delta != dec!(-2) && predictor.bid_delta != Decimal::ZERO {
             if pk_order_num == 0 {
                 let mut price = (long_upper + long_lower) * dec!(0.5);
                 // 不限制大小
@@ -846,7 +846,7 @@ impl Strategy {
 
                 let order_client_id = utils::generate_client_id(Some(self.broker_id.clone()));
                 let order = vec![
-                    predictor.pos_amount.abs().to_string(),
+                    predictor.ready_close_amount.to_string(),
                     "pk".to_string(),
                     price.to_string(),
                     order_client_id.clone(),
@@ -996,23 +996,22 @@ impl Strategy {
         //     short_free_value = min(coin_value, self.max_short_value) - sell_value;
         // }
         // 一手开单价值计算
-        let one_hand_long_value = dec!(0.97) * (self.max_long_value / self.grid);
-        let one_hand_short_value = dec!(0.97) * (self.max_short_value / self.grid);
+        // let one_hand_long_value = dec!(0.97) * predictor.one_grid_order_value;
+        // let one_hand_short_value = dec!(0.97) * predictor.one_grid_order_value;
+
         // 挂多单
-        if buy_value == Decimal::ZERO && predictor.inventory.is_zero() && predictor.bid_delta != dec!(-2) {
+        if buy_value.is_zero() && predictor.inventory < predictor.params.grid && predictor.bid_delta.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);
-            let amount = if predictor.inventory < Decimal::ZERO {
-                predictor.pos_amount.abs()
-            } else {
-                let value = min(one_hand_long_value, long_free_value);
-                utils::fix_amount(value / self.mp, self.step_size)
-            };
+
+            let value = min(long_free_value, predictor.one_grid_order_value);
+            let amount = utils::fix_amount(value / self.mp, self.step_size);
 
             // 下单价值判定
             let amount_value = amount * target_buy_price;
             if amount_value >= self.min_amount_value || predictor.inventory < Decimal::ZERO {
+                // predictor.fair_price_when_ordering = predictor.fair_price.clone();
 
                 let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
                 let order = vec![
@@ -1034,21 +1033,18 @@ impl Strategy {
             }
         }
         // 挂空单
-        if sell_value == Decimal::ZERO && predictor.inventory.is_zero() && predictor.ask_delta != dec!(-2) {
+        if sell_value.is_zero() && predictor.inventory > -predictor.params.grid && predictor.ask_delta.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));
             // 取消大小限制
             target_sell_price = utils::fix_price(target_sell_price, self.tick_size);
-            let amount = if predictor.inventory > Decimal::ZERO {
-                predictor.pos_amount.abs()
-            } else {
-                let value = min(one_hand_short_value, short_free_value);
-                utils::fix_amount(value / self.mp, self.step_size)
-            };
+            let value = min(short_free_value, predictor.one_grid_order_value);
+            let amount = utils::fix_amount(value / self.mp, self.step_size);
 
             // 下单价值不能太大,也不能太小
             let amount_value = amount * target_sell_price;
             if amount_value >= self.min_amount_value || predictor.inventory > Decimal::ZERO {
+                // predictor.fair_price_when_ordering = predictor.fair_price.clone();
 
                 let client_id = utils::generate_client_id(Some(self.broker_id.clone()));
                 let order = vec![
@@ -1107,7 +1103,7 @@ impl Strategy {
 
         self.ref_ap = predictor.optimal_ask_price;
         self.ref_bp = predictor.optimal_bid_price;
-        self.ref_price = predictor.mid_price;
+        self.ref_price = predictor.fair_price;
         self.mp = predictor.mid_price;
 
         // 修复相关价格