|
|
@@ -16,7 +16,8 @@ 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 flow_ratio_short_vec: FixedTimeRangeDeque<Decimal>, // 資金流歷史記錄
|
|
|
+ pub flow_ratio_long_vec: FixedTimeRangeDeque<Decimal>, // 資金流歷史記錄
|
|
|
|
|
|
pub mid_price: Decimal, // 中间价
|
|
|
pub ask_price: Decimal, // 卖一价
|
|
|
@@ -37,7 +38,8 @@ pub struct AvellanedaStoikov {
|
|
|
pub flow_in_value: Decimal,
|
|
|
pub flow_out_value: Decimal,
|
|
|
pub flow_ratio: Decimal, // 资金流比例
|
|
|
- pub flow_ratio_change: Decimal, // 最近的資金流變化情況
|
|
|
+ pub flow_ratio_change_short: Decimal, // 最近的資金流變化情況
|
|
|
+ pub flow_ratio_change_long: Decimal, // 最近的資金流變化情況
|
|
|
|
|
|
pub ask_delta: Decimal, // δa
|
|
|
pub bid_delta: Decimal, // δb
|
|
|
@@ -70,7 +72,8 @@ impl AvellanedaStoikov {
|
|
|
depth_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_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),
|
|
|
+ flow_ratio_long_vec: FixedTimeRangeDeque::new(3 * Self::FLOW_RATIO_RANGE_MICROS),
|
|
|
+ flow_ratio_short_vec: FixedTimeRangeDeque::new(Self::FLOW_RATIO_RANGE_MICROS),
|
|
|
|
|
|
mid_price: Default::default(),
|
|
|
ask_price: Default::default(),
|
|
|
@@ -100,7 +103,8 @@ impl AvellanedaStoikov {
|
|
|
prev_trade_time: Utc::now().timestamp_micros(),
|
|
|
t_diff: Default::default(),
|
|
|
flow_ratio: Decimal::ONE,
|
|
|
- flow_ratio_change: Default::default(),
|
|
|
+ flow_ratio_change_short: Default::default(),
|
|
|
+ flow_ratio_change_long: Default::default(),
|
|
|
flow_in_value: Default::default(),
|
|
|
flow_out_value: Default::default(),
|
|
|
level: Default::default(),
|
|
|
@@ -281,27 +285,27 @@ impl AvellanedaStoikov {
|
|
|
self.ask_delta += pos_edge;
|
|
|
}
|
|
|
|
|
|
- if self.flow_ratio < Decimal::ZERO {
|
|
|
- if self.flow_ratio_change > dec!(0.01) || self.inventory > Decimal::ZERO {
|
|
|
- self.ask_delta -= self.base_delta * dec!(2);
|
|
|
- self.bid_delta += self.base_delta * dec!(2);
|
|
|
- } else if self.flow_ratio_change < dec!(-0.01) && self.inventory < Decimal::ZERO {
|
|
|
- self.ask_delta += self.base_delta * dec!(2);
|
|
|
- self.bid_delta -= self.base_delta * dec!(2);
|
|
|
+ if self.flow_ratio_change_long < Decimal::ZERO {
|
|
|
+ if self.flow_ratio_change_short > dec!(0.05) {
|
|
|
+ self.ask_delta -= self.base_delta;
|
|
|
+ self.bid_delta += self.base_delta * dec!(3);
|
|
|
+ } else if self.flow_ratio_change_short < dec!(-0.15) && self.inventory < Decimal::ZERO {
|
|
|
+ self.ask_delta += self.base_delta * dec!(3);
|
|
|
+ self.bid_delta -= self.base_delta;
|
|
|
} else {
|
|
|
- self.ask_delta += self.base_delta * dec!(2);
|
|
|
- self.bid_delta += self.base_delta * dec!(2);
|
|
|
+ self.ask_delta += self.base_delta * dec!(3);
|
|
|
+ self.bid_delta += self.base_delta * dec!(3);
|
|
|
}
|
|
|
- } else if self.flow_ratio > Decimal::ZERO {
|
|
|
- if self.flow_ratio_change > dec!(0.01) && self.inventory > Decimal::ZERO {
|
|
|
- self.ask_delta -= self.base_delta * dec!(2);
|
|
|
- self.bid_delta += self.base_delta * dec!(2);
|
|
|
- } else if self.flow_ratio_change < dec!(-0.01) || self.inventory < Decimal::ZERO {
|
|
|
- self.ask_delta += self.base_delta * dec!(2);
|
|
|
- self.bid_delta -= self.base_delta * dec!(2);
|
|
|
+ } else if self.flow_ratio_change_long > Decimal::ZERO {
|
|
|
+ if self.flow_ratio_change_short > dec!(0.15) && self.inventory > Decimal::ZERO {
|
|
|
+ self.ask_delta -= self.base_delta;
|
|
|
+ self.bid_delta += self.base_delta * dec!(3);
|
|
|
+ } else if self.flow_ratio_change_short < dec!(-0.05) {
|
|
|
+ self.ask_delta += self.base_delta * dec!(3);
|
|
|
+ self.bid_delta -= self.base_delta;
|
|
|
} else {
|
|
|
- self.ask_delta += self.base_delta * dec!(2);
|
|
|
- self.bid_delta += self.base_delta * dec!(2);
|
|
|
+ self.ask_delta += self.base_delta * dec!(3);
|
|
|
+ self.bid_delta += self.base_delta * dec!(3);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -326,19 +330,26 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
pub fn update_flow_ratio(&mut self) {
|
|
|
- if self.flow_out_value + self.flow_in_value > dec!(100_000) {
|
|
|
+ if self.flow_out_value + self.flow_in_value > dec!(300_000) {
|
|
|
// 使用EMA來更新資金流,確保平滑性
|
|
|
let a = Decimal::TWO / dec!(50);
|
|
|
let now = (self.flow_in_value - self.flow_out_value) / (self.flow_out_value + self.flow_in_value);
|
|
|
self.flow_ratio = a * now + (Decimal::ONE - a) * self.flow_ratio;
|
|
|
- self.flow_ratio_vec.push_back(self.flow_ratio);
|
|
|
+ self.flow_ratio_long_vec.push_back(self.flow_ratio);
|
|
|
+ self.flow_ratio_short_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];
|
|
|
+ if self.flow_ratio_short_vec.len() > 2 {
|
|
|
+ let last = self.flow_ratio_short_vec.deque.iter().last().unwrap().clone();
|
|
|
+ let first = self.flow_ratio_short_vec.deque[0];
|
|
|
|
|
|
- self.flow_ratio_change = last - first;
|
|
|
+ self.flow_ratio_change_short = last - first;
|
|
|
+ }
|
|
|
+ if self.flow_ratio_long_vec.len() > 2 {
|
|
|
+ let last = self.flow_ratio_long_vec.deque.iter().last().unwrap().clone();
|
|
|
+ let first = self.flow_ratio_long_vec.deque[0];
|
|
|
+
|
|
|
+ self.flow_ratio_change_long = last - first;
|
|
|
}
|
|
|
} else {
|
|
|
self.flow_ratio = Decimal::ZERO;
|
|
|
@@ -421,9 +432,9 @@ impl AvellanedaStoikov {
|
|
|
optimal_bid_price: self.optimal_bid_price,
|
|
|
|
|
|
inventory: self.inventory,
|
|
|
- sigma_square: self.flow_ratio,
|
|
|
- gamma: self.flow_ratio_change,
|
|
|
- kappa: self.t_diff,
|
|
|
+ sigma_square: self.flow_ratio_change_long,
|
|
|
+ gamma: self.flow_ratio_change_short,
|
|
|
+ kappa: self.flow_ratio,
|
|
|
|
|
|
flow_ratio: self.flow_ratio,
|
|
|
ref_price: self.ref_price,
|