Răsfoiți Sursa

資金流指標更新。

skyfffire 1 an în urmă
părinte
comite
f57f15f1af
2 a modificat fișierele cu 73 adăugiri și 24 ștergeri
  1. 68 19
      strategy/src/avellaneda_stoikov.rs
  2. 5 5
      strategy/src/strategy.rs

+ 68 - 19
strategy/src/avellaneda_stoikov.rs

@@ -16,6 +16,7 @@ pub struct AvellanedaStoikov {
     pub depth_vec: FixedTimeRangeDeque<Depth>,                                  // 深度队列
     pub trade_vec: FixedTimeRangeDeque<Trade>,                                  // 交易队列
     pub spread_vec: FixedTimeRangeDeque<Decimal>,
+    pub flow_ratio_vec: FixedTimeRangeDeque<Decimal>,                           // 資金流歷史記錄
 
     pub mid_price: Decimal,                                                     // 中间价
     pub ask_price: Decimal,                                                     // 卖一价
@@ -36,6 +37,7 @@ pub struct AvellanedaStoikov {
     pub flow_in_value: Decimal,
     pub flow_out_value: Decimal,
     pub flow_ratio: Decimal,                                                    // 资金流比例
+    pub flow_ratio_change: Decimal,                                             // 最近的資金流變化情況
 
     pub ask_delta: Decimal,                                                     // δa
     pub bid_delta: Decimal,                                                     // δb
@@ -49,12 +51,15 @@ pub struct AvellanedaStoikov {
     pub is_ready: bool,
     pub prev_trade_time: i64,                                                   // 上次交易时间,也就是t
     pub t_diff: Decimal,                                                        // (T-t)
+    pub prev_close_time: i64,                                                   // 上次平倉時間
+    pub prev_prev_close_time: i64,                                              // 上上次平倉時間
 }
 
 impl AvellanedaStoikov {
     // 时间窗口大小(微秒)
     const MAX_TIME_RANGE_MICROS: i64 = 5 * 60_000_000;
     const TRADE_RANGE_MICROS: i64 = 3 * 60_000_000;
+    const FLOW_RATIO_RANGE_MICROS: i64 = 1 * 60_000_000;
     // const ONE_MILLION: Decimal = dec!(1_000_000);
     // const TWENTY_THOUSAND: Decimal = dec!(20_000);
     const IRA: Decimal = dec!(1);
@@ -63,8 +68,9 @@ impl AvellanedaStoikov {
         let avellaneda_stoikov = Self {
             // 分别给与的长度
             depth_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
-            trade_vec: FixedTimeRangeDeque::new(Self::TRADE_RANGE_MICROS),
             spread_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
+            trade_vec: FixedTimeRangeDeque::new(Self::TRADE_RANGE_MICROS),
+            flow_ratio_vec: FixedTimeRangeDeque::new(Self::FLOW_RATIO_RANGE_MICROS),
 
             mid_price: Default::default(),
             ask_price: Default::default(),
@@ -86,7 +92,6 @@ impl AvellanedaStoikov {
 
             ratio_edge: Default::default(),
             kappa: Default::default(),
-            flow_in_value: Default::default(),
             ref_price: Default::default(),
 
             cci_arc,
@@ -95,8 +100,12 @@ impl AvellanedaStoikov {
             prev_trade_time: Utc::now().timestamp_micros(),
             t_diff: Default::default(),
             flow_ratio: Decimal::ONE,
+            flow_ratio_change: Default::default(),
+            flow_in_value: Default::default(),
             flow_out_value: Default::default(),
             level: Default::default(),
+            prev_close_time: Utc::now().timestamp_micros(),
+            prev_prev_close_time: Utc::now().timestamp_micros(),
         };
 
         avellaneda_stoikov
@@ -157,27 +166,54 @@ impl AvellanedaStoikov {
     }
 
     pub async fn on_trade(&mut self, trade: &Trade) {
-        self.trade_vec.push_back(trade.clone());
-        self.flow_in_value = Decimal::ZERO;
-        self.flow_out_value = Decimal::ZERO;
-        for (index, trade_iter) in self.trade_vec.deque.iter().enumerate() {
-            if index == 0 {
-                continue
-            }
-            let prev_trade_iter = self.trade_vec.get(index - 1).unwrap();
+        if self.trade_vec.deque.len() > 0 {
+            let prev_trade_iter = self.trade_vec.deque.iter().last().unwrap();
 
-            if trade_iter.price > prev_trade_iter.price {
-                self.flow_in_value += trade_iter.value;
-            } else if trade_iter.price < prev_trade_iter.price {
-                self.flow_out_value += trade_iter.value;
+            if trade.price > prev_trade_iter.price {
+                self.flow_in_value += trade.value;
+            } else if trade.price < prev_trade_iter.price {
+                self.flow_out_value += trade.value;
             } else {
-                if trade_iter.size > Decimal::ZERO {
-                    self.flow_in_value += trade_iter.value;
+                if trade.size > Decimal::ZERO {
+                    self.flow_in_value += trade.value;
                 } else {
-                    self.flow_out_value += trade_iter.value;
+                    self.flow_out_value += trade.value;
                 }
             }
+
+            if self.flow_out_value + self.flow_in_value > dec!(1_000_000) {
+                self.flow_out_value = self.flow_out_value * dec!(0.618);
+                self.flow_in_value = self.flow_in_value * dec!(0.618);
+            }
+        } else {
+            if trade.size > Decimal::ZERO {
+                self.flow_in_value += trade.value;
+            } else {
+                self.flow_out_value += trade.value;
+            }
         }
+        self.trade_vec.push_back(trade.clone());
+
+        // self.flow_in_value = Decimal::ZERO;
+        // self.flow_out_value = Decimal::ZERO;
+        // for (index, trade_iter) in self.trade_vec.deque.iter().enumerate() {
+        //     if index == 0 {
+        //         continue
+        //     }
+        //     let prev_trade_iter = self.trade_vec.get(index - 1).unwrap();
+        //
+        //     if trade_iter.price > prev_trade_iter.price {
+        //         self.flow_in_value += trade_iter.value;
+        //     } else if trade_iter.price < prev_trade_iter.price {
+        //         self.flow_out_value += trade_iter.value;
+        //     } else {
+        //         if trade_iter.size > Decimal::ZERO {
+        //             self.flow_in_value += trade_iter.value;
+        //         } else {
+        //             self.flow_out_value += trade_iter.value;
+        //         }
+        //     }
+        // }
 
         self.last_price = trade.price;
         self.update_spread();
@@ -193,6 +229,10 @@ impl AvellanedaStoikov {
         self.prev_trade_time = Utc::now().timestamp_micros();
         self.inventory = (inventory / (min_amount_value / self.mid_price)).round();
 
+        // if self.inventory.is_zero() {
+        //     self.prev_prev_close_time = self.prev_close_time;
+        //     self.prev_close_time = Utc::now().timestamp_millis();
+        // }
         self.update_level().await;
         self.processor().await;
     }
@@ -240,7 +280,7 @@ impl AvellanedaStoikov {
         if self.gamma != Decimal::ZERO {
             let pos_edge = self.gamma * self.sigma_square * self.inventory.abs().powd(Decimal::TWO) * self.t_diff / Decimal::TWO;
 
-            self.base_delta = self.gamma * self.sigma_square * self.t_diff / Decimal::TWO + (Decimal::ONE / self.gamma) * (Decimal::ONE + self.gamma / self.kappa).ln();
+            self.base_delta = self.sigma_square;
             self.ratio_edge = self.flow_ratio * self.sigma_square;
 
             self.bid_delta = self.base_delta;
@@ -281,6 +321,15 @@ impl AvellanedaStoikov {
     pub fn update_flow_ratio(&mut self) {
         if self.trade_vec.len() > 100 {
             self.flow_ratio = (self.flow_in_value - self.flow_out_value) / (self.flow_out_value + self.flow_in_value);
+            self.flow_ratio_vec.push_back(self.flow_ratio);
+
+            // 更新最後的變化
+            if self.flow_ratio_vec.len() > 10 {
+                let last = self.flow_ratio_vec.deque.iter().last().unwrap().clone();
+                let first = self.flow_ratio_vec.deque[0];
+
+                self.flow_ratio_change = last - first;
+            }
         } else {
             self.flow_ratio = Decimal::ZERO;
         }
@@ -363,7 +412,7 @@ impl AvellanedaStoikov {
 
             inventory: self.inventory,
             sigma_square: self.flow_ratio,
-            gamma: self.ratio_edge,
+            gamma: self.flow_ratio_change,
             kappa: self.t_diff,
 
             flow_ratio: self.flow_ratio,

+ 5 - 5
strategy/src/strategy.rs

@@ -826,10 +826,10 @@ impl Strategy {
     pub fn _cancel_open(&self, command: &mut OrderCommand, local_orders: &HashMap<String, OrderInfo>) {
         // debug!(?command);
         // 挂单范围
-        let long_upper = self.open_dist[0];
-        let long_lower = self.open_dist[1];
-        let short_lower = self.open_dist[2];
-        let short_upper = self.open_dist[3];
+        // let long_upper = self.open_dist[0];
+        // let long_lower = self.open_dist[1];
+        // let short_lower = self.open_dist[2];
+        // let short_upper = self.open_dist[3];
 
         for order_client_id in local_orders.keys() {
             let order = local_orders.get(order_client_id).unwrap();
@@ -1095,7 +1095,7 @@ impl Strategy {
         }
 
         self._cancel_open(&mut command, local_orders);              // 撤单命令处理
-        self._post_open(&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
         self._check_request_limit(&mut command);                    // 限制频率,移除不合规则之订单,是一个filter