Prechádzať zdrojové kódy

v1.0.21: 用时间平仓,做时间的朋友

skyffire 9 mesiacov pred
rodič
commit
02ca14caeb
3 zmenil súbory, kde vykonal 64 pridanie a 45 odobranie
  1. 3 3
      global/src/params.rs
  2. 9 1
      strategy/src/core.rs
  3. 52 41
      strategy/src/predictor.rs

+ 3 - 3
global/src/params.rs

@@ -46,8 +46,8 @@ pub struct Params {
     pub gamma: Decimal,
     // 分批建仓功能 小资金建议1 大资金建议3 默认 1
     pub grid: Decimal,
-    // 平仓难度, [easy, normal, hard]
-    pub close_difficulty: String,
+    // 持仓时间
+    pub holding_time: Decimal,
     // 是否启用colocation技术, 1开启,0关闭 默认0
     pub colo: i8,
     // 日志级别,从低到高依次是:[trace, debug, info, warn, error]
@@ -97,7 +97,7 @@ impl Params {
             stop_loss: Decimal::try_from(json_value["stop_loss"].as_f64().unwrap_or_default()).unwrap(),
             hold_coin: Decimal::ZERO,
             grid: Decimal::try_from(json_value["grid"].as_f64().unwrap_or_default()).unwrap(),
-            close_difficulty: json_value["close_difficulty"].as_str().unwrap().to_string(),
+            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(),

+ 9 - 1
strategy/src/core.rs

@@ -387,7 +387,9 @@ impl Core {
                                 self.local_cash -= filled * filled_price;
                                 self.local_coin = filled - fee;
 
-                                // sell 平多
+                                self.predictor.on_order(side, filled).await
+
+                            // sell 平多
                             } else if side == "pd" {
                                 self.local_sell_amount += filled;
                                 self.local_sell_value += filled * filled_price;
@@ -402,6 +404,8 @@ impl Core {
                                 self.local_cash += filled * filled_price - fee;
                                 self.local_coin -= filled;
 
+                                self.predictor.on_order(side, filled).await
+
                             // buy 平空
                             } else if side == "pk" {
                                 self.local_buy_amount += filled - fee;
@@ -417,6 +421,8 @@ impl Core {
                                 self.local_cash -= filled * filled_price;
                                 self.local_coin += filled - fee;
 
+                                self.predictor.on_order(side, filled).await
+
                             // sell 开空
                             } else if side == "kk" {
                                 self.local_sell_amount += filled;
@@ -432,6 +438,8 @@ impl Core {
                                 }
                                 self.local_cash += filled * filled_price - fee;
                                 self.local_coin -= filled;
+
+                                self.predictor.on_order(side, filled).await
                             } else {
                                 info!("错误的仓位方向{}", side);
                             }

+ 52 - 41
strategy/src/predictor.rs

@@ -1,5 +1,5 @@
 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;
@@ -75,7 +75,11 @@ pub struct Predictor {
 
     pub params: Params,
 
-    pub debug_sender: UnboundedSender<Vec<Decimal>>
+    pub debug_sender: UnboundedSender<Vec<Decimal>>,
+
+    pub trade_time_vec: VecDeque<Decimal>,                                      // 交易时间队列
+    pub trade_side_map: HashMap<Decimal, String>,                               // 交易时间,对应的是kk,kd两个方向
+    pub trade_amount_map: HashMap<Decimal, Decimal>,                            // 交易数量
 }
 
 impl Predictor {
@@ -191,6 +195,10 @@ impl Predictor {
             params,
 
             debug_sender: tx,
+
+            trade_time_vec: VecDeque::new(),
+            trade_side_map: HashMap::new(),
+            trade_amount_map: HashMap::new(),
         };
 
         predictor
@@ -253,6 +261,22 @@ impl Predictor {
         }
     }
 
+    // side, pk,pd从HashMap移除,kd,kk添加到HashMap
+    pub async fn on_order(&mut self, side: String, amount: Decimal) {
+        if side == "kk" || side == "kd" {
+            let now = Decimal::from(Utc::now().timestamp_millis());
+
+            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);
+        }
+    }
+
     pub async fn update_level(&mut self) {
         self.level = (Decimal::NEGATIVE_ONE + (Decimal::ONE + dec!(8) * self.inventory.abs()).sqrt().unwrap()) / Decimal::TWO;
         self.level = min(self.level, dec!(6));
@@ -384,49 +408,36 @@ impl Predictor {
         }
 
         // 可能是接针
-        let is_open_long = self.force_order_value < -self.params.open
-            && self.inventory < self.params.grid
-            && self.inventory >= Decimal::ZERO
-            && (self.mid_price < self.prev_trade_price * dec!(0.99) || self.prev_trade_price.is_zero())
-            && self.force_order_value < self.prev_trade_force_order_value;
-        let is_open_short = self.force_order_value > self.params.open
-            && self.inventory > -self.params.grid
-            && self.inventory <= Decimal::ZERO
-            && (self.mid_price > self.prev_trade_price * dec!(1.01) || self.prev_trade_price.is_zero())
-            && self.force_order_value > self.prev_trade_force_order_value;
-
-        let (is_close_long, is_close_short) = match self.params.close_difficulty.as_str() {
-            "easy" => {
-                let is_close_long = self.inventory > Decimal::ZERO && self.force_order_value > Decimal::ZERO;
-                let is_close_short = self.inventory < Decimal::ZERO && self.force_order_value < Decimal::ZERO;
-
-                (is_close_long, is_close_short)
-            },
-            "normal" => {
-                let is_close_long = self.inventory > Decimal::ZERO && self.force_order_value > self.params.open * dec!(0.5);
-                let is_close_short = self.inventory < Decimal::ZERO && self.force_order_value < -self.params.open * dec!(0.5);
-
-                (is_close_long, is_close_short)
-            },
-            "hard" => {
-                let is_close_long = self.inventory > Decimal::ZERO && self.force_order_value > self.params.open;
-                let is_close_short = self.inventory < Decimal::ZERO && self.force_order_value < -self.params.open;
-
-                (is_close_long, is_close_short)
-            }
-            _ => {
-                panic!("错误的平仓条件:{}", self.params.close_difficulty)
-            }
-        };
+        let is_open_long = self.force_order_value < -self.params.open && self.inventory < self.params.grid;
+        let is_open_short = self.force_order_value > self.params.open && self.inventory > -self.params.grid;
 
         self.bid_delta = dec!(-2);
         self.ask_delta = dec!(-2);
 
-        if is_close_long {
-            self.ask_delta = self.mid_price * self.params.close;
-        } else if is_close_short {
-            self.bid_delta = self.mid_price * self.params.close;
-        } else if is_open_long {
+        // 平仓优先级高一些
+        if self.trade_time_vec.len() > 0 {
+            let first = self.trade_time_vec.front().unwrap();
+            let now = Decimal::from(Utc::now().timestamp_millis());
+
+            if now - self.params.holding_time * Decimal::ONE_THOUSAND > *first {
+                let side = self.trade_side_map.get(first).unwrap();
+                let _ = self.trade_amount_map.get(first).unwrap();
+
+                match side.as_str() {
+                    "kd" => {
+                        self.ask_delta = Decimal::ZERO;
+                    }
+                    "kk" => {
+                        self.bid_delta = Decimal::ZERO;
+                    }
+                    &_ => {
+                        panic!("什么方向放进来了?side={}", side);
+                    }
+                }
+            }
+        }
+
+        if is_open_long {
             self.bid_delta = Decimal::ZERO;
         } else if is_open_short {
             self.ask_delta = Decimal::ZERO;