瀏覽代碼

加入長周期觀察。

skyfffire 1 年之前
父節點
當前提交
75e7abb671
共有 1 個文件被更改,包括 108 次插入36 次删除
  1. 108 36
      strategy/src/avellaneda_stoikov.rs

+ 108 - 36
strategy/src/avellaneda_stoikov.rs

@@ -14,7 +14,8 @@ use standard::{Depth, Ticker, Trade};
 #[derive(Debug)]
 pub struct AvellanedaStoikov {
     pub depth_vec: FixedTimeRangeDeque<Depth>,                                  // 深度队列
-    pub trade_vec: FixedTimeRangeDeque<Trade>,                                  // 交易队列
+    pub trade_long_vec: FixedTimeRangeDeque<Trade>,                             // 交易队列
+    pub trade_short_vec: FixedTimeRangeDeque<Trade>,                            // 交易队列
     pub spread_vec: FixedTimeRangeDeque<Decimal>,
 
     pub mid_price: Decimal,                                                     // 中间价
@@ -33,9 +34,8 @@ pub struct AvellanedaStoikov {
     pub gamma: Decimal,                                                         // γ,库存风险厌恶参数
     pub kappa: Decimal,                                                         // κ 订单簿 流动性 参数
 
-    pub flow_in_value: Decimal,
-    pub flow_out_value: Decimal,
-    pub flow_ratio: Decimal,                                                    // 资金流比例
+    pub flow_ratio_long: Decimal,                                               // 资金流比例
+    pub flow_ratio_short: Decimal,                                              // 资金流比例
 
     pub ask_delta: Decimal,                                                     // δa
     pub bid_delta: Decimal,                                                     // δb
@@ -54,6 +54,8 @@ pub struct AvellanedaStoikov {
 impl AvellanedaStoikov {
     // 时间窗口大小(微秒)
     const MAX_TIME_RANGE_MICROS: i64 = 3 * 60_000_000;
+    const TRADE_LONG_RANGE_MICROS: i64 = 3 * 60_000_000;
+    const TRADE_SHORT_RANGE_MICROS: i64 = 20_000_000;
     // const ONE_MILLION: Decimal = dec!(1_000_000);
     // const TWENTY_THOUSAND: Decimal = dec!(20_000);
     const IRA: Decimal = dec!(1);
@@ -62,8 +64,9 @@ impl AvellanedaStoikov {
         let avellaneda_stoikov = Self {
             // 分别给与的长度
             depth_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
-            trade_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
             spread_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
+            trade_long_vec: FixedTimeRangeDeque::new(Self::TRADE_LONG_RANGE_MICROS),
+            trade_short_vec: FixedTimeRangeDeque::new(Self::TRADE_SHORT_RANGE_MICROS),
 
             mid_price: Default::default(),
             ask_price: Default::default(),
@@ -85,7 +88,6 @@ impl AvellanedaStoikov {
 
             ratio_edge: Default::default(),
             kappa: Default::default(),
-            flow_in_value: Default::default(),
             ref_price: Default::default(),
 
             cci_arc,
@@ -93,9 +95,9 @@ impl AvellanedaStoikov {
             is_ready: false,
             prev_trade_time: Utc::now().timestamp_micros(),
             t_diff: Default::default(),
-            flow_ratio: Decimal::ONE,
-            flow_out_value: Default::default(),
+            flow_ratio_long: Decimal::ONE,
             level: Default::default(),
+            flow_ratio_short: Default::default(),
         };
 
         avellaneda_stoikov
@@ -120,14 +122,14 @@ impl AvellanedaStoikov {
     }
 
     pub fn update_spread(&mut self) {
-        if self.trade_vec.len() > 0 {
+        if self.trade_long_vec.len() > 0 {
             //
-            let last_trade = self.trade_vec.get(self.trade_vec.len() - 1).unwrap();
+            let last_trade = self.trade_long_vec.get(self.trade_long_vec.len() - 1).unwrap();
             let last_trade_price = last_trade.price;
             let last_trade_time = last_trade.time;
 
             let mut first_trade_price = last_trade.price;
-            for trade in self.trade_vec.deque.iter().rev() {
+            for trade in self.trade_long_vec.deque.iter().rev() {
                 if last_trade_time - trade.time > Decimal::TEN {
                     break;
                 }
@@ -156,22 +158,10 @@ 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 trade_iter in self.trade_vec.deque.iter() {
-            if trade_iter.size > Decimal::ZERO {
-                self.flow_in_value += trade_iter.value;
-            } else {
-                self.flow_out_value += trade_iter.value;
-            }
-        }
+        self.trade_long_vec.push_back(trade.clone());
+        self.trade_short_vec.push_back(trade.clone());
 
-        if self.last_price != trade.price {
-            self.last_price = trade.price;
-        } else {
-            self.last_price = Decimal::ZERO;
-        }
+        self.last_price = trade.price;
         self.update_spread();
         self.processor().await;
     }
@@ -233,7 +223,7 @@ impl AvellanedaStoikov {
             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.ratio_edge = self.flow_ratio * self.sigma_square;
+            self.ratio_edge = self.flow_ratio_long * self.sigma_square;
 
             self.bid_delta = self.base_delta;
             self.ask_delta = self.base_delta;
@@ -272,14 +262,96 @@ impl AvellanedaStoikov {
         }
     }
 
-    pub fn update_flow_ratio(&mut self) {
-        if self.trade_vec.len() > 200 {
-            self.flow_ratio = (self.flow_in_value - self.flow_out_value) / (self.flow_out_value + self.flow_in_value);
+    fn calc_flow_ratio(_prev_flow_ratio: &Decimal, min_volume: &Decimal, trades: &mut FixedTimeRangeDeque<Trade>) -> Decimal {
+        // let mut flow_in_value = Decimal::ZERO;
+        // let mut flow_out_value = Decimal::ZERO;
+        // for (index, trade_iter) in trades.deque.iter().enumerate() {
+        //     if index == 0 {
+        //         continue
+        //     }
+        //
+        //     let prev_trade_iter = trades.deque.get(index - 1).unwrap();
+        //     let trade = trade_iter;
+        //     if trade.price > prev_trade_iter.price {
+        //         flow_in_value += trade.value * (prev_trade_iter.price - trade.price).abs();
+        //         // flow_in_value += Decimal::ONE;
+        //     } else if trade.price < prev_trade_iter.price {
+        //         flow_out_value += trade.value * (prev_trade_iter.price - trade.price).abs();
+        //         // flow_out_value += Decimal::ONE;
+        //     } else {
+        //         // if trade.size > Decimal::ZERO {
+        //         //     flow_in_value += trade.value;
+        //         // } else {
+        //         //     flow_out_value += trade.value;
+        //         // }
+        //     }
+        //
+        //     // if trade_iter.size > Decimal::ZERO {
+        //     //     flow_in_value += trade_iter.value;
+        //     // } else {
+        //     //     flow_out_value += trade_iter.value;
+        //     // }
+        // }
+
+        // if self.trade_vec.deque.len() > 1 {
+        //     let prev_trade_iter = self.trade_vec.deque.get(self.trade_vec.deque.len() - 2).unwrap();
+        //     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.size > Decimal::ZERO {
+        //         //     self.flow_in_value += trade.value;
+        //         // } else {
+        //         //     self.flow_out_value += trade.value;
+        //         // }
+        //     }
+        //
+        //     // if trade.size > Decimal::ZERO {
+        //     //     self.flow_in_value += trade.value;
+        //     // } else {
+        //     //     self.flow_out_value += trade.value;
+        //     // }
+        //
+        //     if self.flow_out_value + self.flow_in_value > dec!(2_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;
+        //     }
+        // }
+
+        let mut flow_in_value = Decimal::ZERO;
+        let mut flow_out_value = Decimal::ZERO;
+        for trade_iter in trades.deque.iter() {
+            if trade_iter.size > Decimal::ZERO {
+                flow_in_value += trade_iter.value;
+            } else {
+                flow_out_value += trade_iter.value;
+            }
+        }
+
+        // 使用EMA來更新資金流,確保平滑性
+        // let a = Decimal::TWO / dec!(50);
+        if flow_out_value + flow_in_value > *min_volume {
+            // let now = (flow_in_value - flow_out_value) / (flow_out_value + flow_in_value);
+            // a * now + (Decimal::ONE - a) * prev_flow_ratio
+            (flow_in_value - flow_out_value) / (flow_out_value + flow_in_value)
         } else {
-            self.flow_ratio = Decimal::ZERO;
+            Decimal::ZERO
         }
     }
 
+    pub fn update_flow_ratio(&mut self) {
+        self.flow_ratio_long = Self::calc_flow_ratio(&self.flow_ratio_long, &dec!(0), &mut self.trade_long_vec);
+        self.flow_ratio_short = Self::calc_flow_ratio(&self.flow_ratio_short, &dec!(0), &mut self.trade_short_vec);
+    }
+
     pub fn check_ready(&mut self) {
         if self.is_ready {
             return;
@@ -309,7 +381,7 @@ impl AvellanedaStoikov {
             return;
         }
 
-        if self.trade_vec.len() < 100 {
+        if self.trade_long_vec.len() < 100 {
             return;
         }
 
@@ -345,7 +417,7 @@ impl AvellanedaStoikov {
         cci.predictor_state_vec.push_back(PredictorState {
             update_time: Decimal::from_i64(Utc::now().timestamp_millis()).unwrap(),
 
-            mid_price: self.mid_price,
+            mid_price: self.last_price,
             ask_price: self.ask_price,
             bid_price: self.bid_price,
             last_price: self.last_price,
@@ -356,11 +428,11 @@ impl AvellanedaStoikov {
             optimal_bid_price: self.optimal_bid_price,
 
             inventory: self.inventory,
-            sigma_square: self.flow_ratio,
-            gamma: self.ratio_edge,
+            sigma_square: self.flow_ratio_long,
+            gamma: self.flow_ratio_short,
             kappa: self.t_diff,
 
-            flow_ratio: self.flow_ratio,
+            flow_ratio: self.flow_ratio_long,
             ref_price: self.ref_price,
         });
     }