浏览代码

AS基础版。

skyffire 1 年之前
父节点
当前提交
95ed1bf3cb
共有 1 个文件被更改,包括 134 次插入238 次删除
  1. 134 238
      strategy/src/avellaneda_stoikov.rs

+ 134 - 238
strategy/src/avellaneda_stoikov.rs

@@ -14,14 +14,12 @@ use standard::{Depth, Ticker, Trade};
 #[derive(Debug)]
 pub struct AvellanedaStoikov {
     pub depth_vec: FixedTimeRangeDeque<Depth>,                                  // 深度队列
-    pub trade_long_vec: FixedTimeRangeDeque<Trade>,                             // 交易队列
-    pub trade_short_vec: FixedTimeRangeDeque<Trade>,                            // 交易队列
+    pub trade_vec: FixedTimeRangeDeque<Trade>,                                  // 交易队列
     pub spread_vec: FixedTimeRangeDeque<Decimal>,
 
     pub mid_price: Decimal,                                                     // 中间价
     pub ask_price: Decimal,                                                     // 卖一价
     pub bid_price: Decimal,                                                     // 买一价
-    pub last_price: Decimal,                                                    // 最后成交价
     pub spread: Decimal,                                                        // 市场冲击
     pub spread_max: Decimal,                                                    // 最大市场冲击
     pub spread_min: Decimal,                                                    // 最小市场冲击
@@ -29,54 +27,43 @@ pub struct AvellanedaStoikov {
     pub optimal_bid_price: Decimal,                                             // 买入挂单价
 
     pub inventory: Decimal,                                                     // 库存,也就是q
-    pub level: Decimal,                                                         // martin
     pub sigma_square: Decimal,                                                  // σ^2,波动性的平方
     pub gamma: Decimal,                                                         // γ,库存风险厌恶参数
     pub kappa: Decimal,                                                         // κ 订单簿 流动性 参数
 
-    pub flow_ratio_long: Decimal,                                               // 资金流比例
-    pub flow_ratio_short: Decimal,                                              // 资金流比例
+    pub flow_in_value: Decimal,
+    pub flow_out_value: Decimal,
+    pub flow_ratio: Decimal,                                                    // 资金流比例
+    pub flow_ratio_diff_log: Decimal,                                           // 一阶导数
 
-    pub ask_delta: Decimal,                                                     // δa
-    pub bid_delta: Decimal,                                                     // δb
-    pub base_delta: Decimal,                                                    // 基础挂单距离
-    pub ratio_edge: Decimal,                                                    // 资金流修正的挂单距离
+    pub delta_ask: Decimal,                                                     // δa
+    pub delta_bid: Decimal,                                                     // δb
     pub ref_price: Decimal,                                                     // 预定价格
-    pub init_delta_plus: Decimal,                                               // 最初的delta之和
 
     pub cci_arc: Arc<Mutex<CentralControlInfo>>,                                // 中控信息
 
     pub is_ready: bool,
     pub prev_trade_time: i64,                                                   // 上次交易时间,也就是t
-    pub cross_time: i64,                                                        // 上次穿過0軸的時間
-    pub cross_time_diff: i64,                                                   // 穿越0軸的diff
-    pub cross_time_diff_avg: i64,                                               // 穿越0軸的diff的平均值
     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_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 MAX_TIME_RANGE_MICROS: i64 = 3 * 60_000_000;
+    const ONE_MILLION: Decimal = dec!(1_000_000);
+    const TWENTY_THOUSAND: Decimal = dec!(20_000);
     const IRA: Decimal = dec!(1);
-
+    
     pub fn new(cci_arc: Arc<Mutex<CentralControlInfo>>) -> Self {
         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(),
             bid_price: Default::default(),
-            last_price: Default::default(),
             spread: Default::default(),
             spread_max: Default::default(),
             spread_min: Default::default(),
@@ -86,28 +73,20 @@ impl AvellanedaStoikov {
             inventory: Default::default(),
             gamma: Default::default(),
             sigma_square: Default::default(),
-            ask_delta: Default::default(),
-            bid_delta: Default::default(),
-            base_delta: Default::default(),
-            init_delta_plus: Default::default(),
-
-            ratio_edge: Default::default(),
+            delta_ask: Default::default(),
+            delta_bid: Default::default(),
             kappa: Default::default(),
+            flow_in_value: Default::default(),
             ref_price: Default::default(),
 
             cci_arc,
 
             is_ready: false,
-            prev_trade_time: Utc::now().timestamp_micros(),
-            cross_time: 0,
-            cross_time_diff: 0,
-            cross_time_diff_avg: 0,
+            prev_trade_time: 0,
             t_diff: Default::default(),
-            flow_ratio_long: Decimal::ONE,
-            level: Default::default(),
-            prev_close_time: Utc::now().timestamp_micros(),
-            prev_prev_close_time: Utc::now().timestamp_micros(),
-            flow_ratio_short: Default::default(),
+            flow_ratio: Decimal::ONE,
+            flow_ratio_diff_log: Default::default(),
+            flow_out_value: Default::default(),
         };
 
         avellaneda_stoikov
@@ -132,14 +111,14 @@ impl AvellanedaStoikov {
     }
 
     pub fn update_spread(&mut self) {
-        if self.trade_long_vec.len() > 0 {
+        if self.trade_vec.len() > 0 {
             //
-            let last_trade = self.trade_long_vec.get(self.trade_long_vec.len() - 1).unwrap();
+            let last_trade = self.trade_vec.get(self.trade_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_long_vec.deque.iter().rev() {
+            for trade in self.trade_vec.deque.iter().rev() {
                 if last_trade_time - trade.time > Decimal::TEN {
                     break;
                 }
@@ -168,58 +147,84 @@ impl AvellanedaStoikov {
     }
 
     pub async fn on_trade(&mut self, trade: &Trade) {
-        self.trade_long_vec.push_back(trade.clone());
-        self.trade_short_vec.push_back(trade.clone());
+        if trade.size > Decimal::ZERO {
+            self.flow_in_value += trade.value;
+        } else {
+            self.flow_out_value += trade.value;
+        }
+        if self.flow_in_value + self.flow_out_value > Self::ONE_MILLION {
+            self.flow_in_value = self.flow_in_value * dec!(0.618);
+            self.flow_out_value = self.flow_out_value * dec!(0.618);
+        }
 
-        self.last_price = trade.price;
+        self.trade_vec.push_back(trade.clone());
         self.update_spread();
         self.processor().await;
     }
 
-    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));
-    }
+    pub async fn update_inventory(&mut self, inventory: &Decimal, step_size: &Decimal) {
+        let new_inventory = inventory / step_size;
+
+        if self.inventory.abs() < new_inventory.abs() {
+            self.prev_trade_time = Utc::now().timestamp_micros();
+        }
 
-    pub async fn update_inventory(&mut self, inventory: &Decimal, min_amount_value: &Decimal) {
-        self.prev_trade_time = Utc::now().timestamp_micros();
-        self.inventory = (inventory / (min_amount_value / self.mid_price)).round();
+        self.inventory = new_inventory;
 
-        // 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;
     }
 
     pub fn update_sigma_square(&mut self) {
-        self.sigma_square = self.spread_max * dec!(1.618);
+        self.sigma_square = if self.trade_vec.len() < 2 {
+            Decimal::ZERO
+        } else {
+            let last_trade = self.trade_vec.get(self.trade_vec.len() - 1).unwrap();
+
+            let mut volatility_total = Decimal::ZERO;
+            for index in (0..self.trade_vec.len()).rev() {
+                if index == self.trade_vec.len() - 1 {
+                    continue
+                }
+                let trade = self.trade_vec.get(index).unwrap();
+
+                if last_trade.time - trade.time > Decimal::ONE_THOUSAND {
+                    break;
+                }
+
+                let prev_trade = self.trade_vec.get(index + 1).unwrap();
+                let volatility = (trade.price - prev_trade.price).abs();
+                volatility_total += volatility;
+            }
+
+            volatility_total / Decimal::TEN
+        };
+
         self.sigma_square.rescale(10);
     }
 
     pub fn update_gamma(&mut self) {
-        // self.gamma = if self.sigma_square == Decimal::ZERO || self.inventory == Decimal::ZERO {
-        //     Decimal::ONE
-        // } else {
-        //     Self::IRA * (self.spread_max - self.spread_min) / (Decimal::TWO * self.inventory.abs() * self.sigma_square)
-        // };
-        // self.gamma.rescale(8);
-
-        self.gamma = dec!(1) * Self::IRA;
+        self.gamma = Decimal::ONE + Self::IRA * (self.spread_max / self.spread_min).sqrt().unwrap() / Decimal::TEN;
+        self.gamma.rescale(8);
     }
 
     pub fn update_kappa(&mut self) {
-        // self.kappa = if self.spread_max.is_zero() || self.init_delta_plus.is_zero() {
-        //     Decimal::ONE
+        // if self.spread_max == Decimal::ZERO {
+        //     self.kappa = Decimal::ONE;
         // } else {
-        //     let mut temp = self.init_delta_plus * self.gamma - self.sigma_square * self.gamma.powd(Decimal::TWO);
-        //     temp.rescale(6);
+        //     let delta_plus_max = (Decimal::TWO - Self::IRA) * self.spread_max + Self::IRA * self.spread_min;
+        //     let mut temp = (delta_plus_max) * self.gamma - self.sigma_square * self.gamma.powd(Decimal::TWO);
         //
-        //     self.gamma / (temp.exp() - Decimal::ONE)
-        // };
+        //     temp.rescale(6);
         //
-        // self.kappa.rescale(8);
+        //     self.kappa = if temp <= Decimal::ZERO {
+        //         Decimal::TEN
+        //     } else if temp >= Decimal::TEN {
+        //         Decimal::TEN
+        //     } else {
+        //         self.gamma / (temp.exp() - Decimal::ONE)
+        //     };
+        //     self.kappa.rescale(8);
+        // }
 
         if self.mid_price > Decimal::ZERO {
             self.kappa = dec!(888) / self.mid_price;
@@ -229,182 +234,73 @@ impl AvellanedaStoikov {
     }
 
     pub fn update_ref_price(&mut self) {
-        self.ref_price = self.mid_price;
+        self.ref_price = self.mid_price - self.inventory * self.gamma * self.sigma_square * self.t_diff;
     }
 
     pub fn update_delta(&mut self) {
-        let pos_edge = self.gamma * self.sigma_square * self.inventory.abs().powd(Decimal::TWO) * self.t_diff;
-
-        self.base_delta = self.sigma_square;
+        if self.gamma != Decimal::ZERO {
+            let a = (self.gamma * self.sigma_square * self.t_diff) / Decimal::TWO;
+            // let edge = (self.flow_ratio_diff_log.abs() / dec!(0.0003)) * self.gamma * self.sigma_square * self.t_diff;
 
-        self.bid_delta = self.base_delta;
-        self.ask_delta = self.base_delta;
+            self.delta_bid = {
+                let b = (Decimal::ONE / self.gamma) * (Decimal::ONE + self.gamma / self.kappa).ln();
 
-        if self.inventory > Decimal::ZERO {
-            self.bid_delta += pos_edge;
-        } else if self.inventory < Decimal::ZERO {
-            self.ask_delta += pos_edge;
-        }
+                a + b
+            };
 
-        if self.flow_ratio_long.is_zero() || self.cross_time_diff < 20 {
-            self.ask_delta += self.base_delta;
-            self.bid_delta += self.base_delta;
+            self.delta_ask = {
+                let b = (Decimal::ONE / self.gamma) * (Decimal::ONE + self.gamma / self.kappa).ln();
 
-            return;
-        }
-
-        if self.flow_ratio_long < Decimal::ZERO {
-            if self.flow_ratio_short > Decimal::ZERO {
-                self.ask_delta -= self.base_delta * (self.flow_ratio_short.abs() * Decimal::PI);
-                self.bid_delta += self.base_delta;
-            } else if self.flow_ratio_short < Decimal::ZERO && self.inventory < Decimal::ZERO {
-                self.ask_delta += self.base_delta;
-                // self.bid_delta -= self.base_delta * (self.flow_ratio_short.abs() + self.flow_ratio_long.abs());
-                self.bid_delta -= self.base_delta * (self.flow_ratio_short.abs() * dec!(1.5));
-            } else {
-                self.ask_delta += self.base_delta;
-                self.bid_delta += self.base_delta;
-            }
-        } else if self.flow_ratio_long > Decimal::ZERO {
-            if self.flow_ratio_short > Decimal::ZERO && self.inventory > Decimal::ZERO {
-                // self.ask_delta -= self.base_delta * (self.flow_ratio_short.abs() + self.flow_ratio_long.abs());
-                self.ask_delta -= self.base_delta * (self.flow_ratio_short.abs() * dec!(1.5));
-                self.bid_delta += self.base_delta;
-            } else if self.flow_ratio_short < Decimal::ZERO {
-                self.ask_delta += self.base_delta;
-                self.bid_delta -= self.base_delta * (self.flow_ratio_short.abs() * Decimal::PI);
-            } else {
-                self.ask_delta += self.base_delta;
-                self.bid_delta += self.base_delta;
-            }
+                a + b
+            };
         }
     }
 
     pub fn update_optimal_ask_and_bid(&mut self) {
-        self.optimal_ask_price = max(self.ref_price + self.ask_delta / dec!(2), self.ask_price);
-        self.optimal_bid_price = min(self.ref_price - self.bid_delta / dec!(2), self.bid_price);
+        self.optimal_ask_price = max(self.ref_price + self.delta_ask / Decimal::TWO, self.ask_price);
+        self.optimal_bid_price = min(self.ref_price - self.delta_bid / Decimal::TWO, self.bid_price);
     }
 
     pub fn update_t_diff(&mut self) {
-        if self.prev_trade_time > 0 {
-            let time_diff_decimal = Decimal::from_i64(Utc::now().timestamp_micros() - self.prev_trade_time).unwrap();
-            self.t_diff = max(Decimal::ONE - time_diff_decimal / Decimal::from_i64(Self::MAX_TIME_RANGE_MICROS).unwrap(), Decimal::ZERO);
-        } else {
-            self.t_diff = Decimal::ONE;
-        }
+        // let time_diff_decimal = Decimal::from_i64(Utc::now().timestamp_micros() - self.prev_trade_time).unwrap();
+        // self.t_diff = time_diff_decimal / Decimal::from_i64(Self::MAX_TIME_RANGE_MICROS).unwrap();
+        // self.t_diff = min(self.t_diff, Decimal::ONE);
+        self.t_diff = Decimal::ONE;
     }
 
-    fn calc_flow_ratio(_prev_flow_ratio: &Decimal, min_volume: &Decimal, trades: &mut FixedTimeRangeDeque<Trade>) -> Decimal {
-        // 使用EMA來更新資金流,確保平滑性
-        // let a = Decimal::TWO / dec!(50);
-
-        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;
+    pub fn update_flow_ratio(&mut self) {
+        let prev_flow_ratio = self.flow_ratio;
+        self.flow_ratio = if self.trade_vec.len() < 2 {
+            Decimal::ZERO
+        } else {
+            if self.flow_out_value + self.flow_in_value <= Self::TWENTY_THOUSAND {
+                Decimal::ZERO
             } else {
-                // if trade.size > Decimal::ZERO {
-                //     flow_in_value += trade.value;
-                // } else {
-                //     flow_out_value += trade.value;
-                // }
+                self.flow_in_value / self.flow_out_value
             }
+        };
 
-            // if trade_iter.size > Decimal::ZERO {
-            //     flow_in_value += trade_iter.value;
-            // } else {
-            //     flow_out_value += trade_iter.value;
-            // }
-        }
-
-        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.rescale(6);
+        self.flow_ratio = if self.flow_ratio > Decimal::TEN {
             Decimal::ZERO
-        }
-
-        // 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;
-        //     }
-        // }
-
-        // 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;
-        //     }
-        // }
-    }
+        } else if self.flow_ratio < dec!(-10) {
+            Decimal::ZERO
+        } else {
+            self.flow_ratio
+        };
 
-    pub fn update_flow_ratio(&mut self) {
-        let prev_flow_ratio_long = self.flow_ratio_long;
-        self.flow_ratio_long = Self::calc_flow_ratio(&self.flow_ratio_long, &dec!(0), &mut self.trade_long_vec);
-        let time = Utc::now().timestamp_millis();
-        // let mut is_cross = false;
-        if (self.flow_ratio_long > Decimal::ZERO && prev_flow_ratio_long <= Decimal::ZERO)
-            || (self.flow_ratio_long < Decimal::ZERO && prev_flow_ratio_long >= Decimal::ZERO) {
-            self.cross_time = time;
-            // is_cross = true;
-        }
+        if self.flow_ratio != Decimal::ZERO {
+            if prev_flow_ratio != Decimal::ZERO && self.flow_ratio != prev_flow_ratio {
+                let flow_ratio_diff = self.flow_ratio - prev_flow_ratio;
+                let temp = if flow_ratio_diff > Decimal::ZERO {
+                    (flow_ratio_diff + Decimal::ONE).ln()
+                } else {
+                    (flow_ratio_diff.abs() + Decimal::ONE).ln() * Decimal::NEGATIVE_ONE
+                };
 
-        if self.cross_time != 0 {
-            // let prev_cross_time_diff = self.cross_time_diff;
-            self.cross_time_diff = (time - self.cross_time) / 1000;
-
-            // if is_cross {
-            //     self.cross_time_diff_avg = if self.cross_time_diff_avg == 0 {
-            //         prev_cross_time_diff
-            //     } else {
-            //         (self.cross_time_diff_avg * 5 + prev_cross_time_diff * 5) / 10
-            //     };
-            // }
+                self.flow_ratio_diff_log = temp * dec!(0.03) + self.flow_ratio_diff_log * dec!(0.97)
+            }
         }
-
-        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) {
@@ -424,11 +320,11 @@ impl AvellanedaStoikov {
             return;
         }
 
-        if self.optimal_ask_price < self.ask_price {
+        if self.optimal_ask_price <= self.ask_price {
             return;
         }
 
-        if self.optimal_bid_price > self.bid_price {
+        if self.optimal_bid_price >= self.bid_price {
             return;
         }
 
@@ -436,7 +332,7 @@ impl AvellanedaStoikov {
             return;
         }
 
-        if self.trade_long_vec.len() < 100 {
+        if self.trade_vec.len() < 100 {
             return;
         }
 
@@ -472,23 +368,23 @@ impl AvellanedaStoikov {
         cci.predictor_state_vec.push_back(PredictorState {
             update_time: Decimal::from_i64(Utc::now().timestamp_millis()).unwrap(),
 
-            mid_price: self.last_price,
+            mid_price: self.mid_price,
             ask_price: self.ask_price,
             bid_price: self.bid_price,
-            last_price: self.last_price,
             spread: self.spread,
-            spread_max: self.ask_delta,
-            spread_min: self.bid_delta,
+            spread_max: self.spread_max,
+            spread_min: self.spread_min,
             optimal_ask_price: self.optimal_ask_price,
             optimal_bid_price: self.optimal_bid_price,
 
             inventory: self.inventory,
-            sigma_square: self.flow_ratio_long,
-            gamma: self.flow_ratio_short,
-            kappa: Decimal::from(self.cross_time_diff),
+            sigma_square: self.sigma_square,
+            gamma: self.gamma,
+            kappa: self.kappa,
 
-            flow_ratio: self.flow_ratio_long,
+            flow_ratio: self.flow_ratio_diff_log,
             ref_price: self.ref_price,
+            last_price: self.mid_price,
         });
     }