|
|
@@ -40,6 +40,7 @@ pub struct AvellanedaStoikov {
|
|
|
pub last_volume: Decimal, // 最后统计的交易量(过去1秒)
|
|
|
pub flow_ratio_long: Decimal, // 资金流比例
|
|
|
pub flow_ratio_short: Decimal, // 资金流比例
|
|
|
+ pub dir: Decimal, // 方向,-2要跌,-1缓跌,0中立,1缓涨,2急涨
|
|
|
|
|
|
pub ask_delta: Decimal, // δa
|
|
|
pub bid_delta: Decimal, // δb
|
|
|
@@ -107,6 +108,7 @@ impl AvellanedaStoikov {
|
|
|
prev_trade_time: Utc::now().timestamp_micros(),
|
|
|
t_diff: Default::default(),
|
|
|
level: Default::default(),
|
|
|
+ dir: Default::default(),
|
|
|
};
|
|
|
|
|
|
avellaneda_stoikov
|
|
|
@@ -168,9 +170,19 @@ impl AvellanedaStoikov {
|
|
|
|
|
|
pub fn update_volume(&mut self) {
|
|
|
self.last_volume = Decimal::ZERO;
|
|
|
+ let limit = dec!(60) * Decimal::ONE_THOUSAND;
|
|
|
|
|
|
- for trade in self.trade_long_vec.deque.iter().rev() {
|
|
|
- self.last_volume += trade.value;
|
|
|
+ if self.trade_long_vec.len() > 0 {
|
|
|
+ let last_trade = self.trade_long_vec.get(self.trade_long_vec.len() - 1).unwrap();
|
|
|
+ let last_trade_time = last_trade.time;
|
|
|
+
|
|
|
+ for trade in self.trade_long_vec.deque.iter().rev() {
|
|
|
+ if last_trade_time - trade.time > limit {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ self.last_volume += trade.value;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -423,6 +435,50 @@ impl AvellanedaStoikov {
|
|
|
self.flow_ratio_short = Self::calc_flow_ratio(&self.flow_ratio_short, &dec!(0), &mut self.trade_long_vec);
|
|
|
}
|
|
|
|
|
|
+ pub fn update_dir(&mut self) {
|
|
|
+ let volume_diff = self.volume_vec.deque.iter().last().unwrap() - self.volume_vec.get(0).unwrap();
|
|
|
+ let open_interest_diff = self.open_interest_vec.deque.iter().last().unwrap() - self.open_interest_vec.get(0).unwrap();
|
|
|
+ let price_diff = self.trade_long_vec.deque.iter().last().unwrap().price - self.trade_long_vec.get(0).unwrap().price;
|
|
|
+
|
|
|
+ let zero = Decimal::ZERO;
|
|
|
+
|
|
|
+ self.dir =
|
|
|
+ // + + + ++
|
|
|
+ if volume_diff > zero && open_interest_diff > zero && price_diff > zero {
|
|
|
+ dec!(2)
|
|
|
+ }
|
|
|
+ // + + - --
|
|
|
+ else if volume_diff > zero && open_interest_diff > zero && price_diff < zero {
|
|
|
+ dec!(-2)
|
|
|
+ }
|
|
|
+ // - - - -
|
|
|
+ else if volume_diff < zero && open_interest_diff < zero && price_diff < zero {
|
|
|
+ dec!(-1)
|
|
|
+ }
|
|
|
+ // - - + +
|
|
|
+ else if volume_diff < zero && open_interest_diff < zero && price_diff > zero {
|
|
|
+ dec!(1)
|
|
|
+ }
|
|
|
+ // - + + x
|
|
|
+ else if volume_diff < zero && open_interest_diff > zero && price_diff > zero {
|
|
|
+ dec!(0)
|
|
|
+ }
|
|
|
+ // + - + --
|
|
|
+ else if volume_diff > zero && open_interest_diff < zero && price_diff > zero {
|
|
|
+ dec!(-2)
|
|
|
+ }
|
|
|
+ // - + - x
|
|
|
+ else if volume_diff > zero && open_interest_diff < zero && price_diff > zero {
|
|
|
+ dec!(0)
|
|
|
+ }
|
|
|
+ // + - - ++
|
|
|
+ else if volume_diff > zero && open_interest_diff < zero && price_diff > zero {
|
|
|
+ dec!(2)
|
|
|
+ } else {
|
|
|
+ dec!(0)
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
pub fn check_ready(&mut self) {
|
|
|
if self.is_ready {
|
|
|
return;
|
|
|
@@ -484,6 +540,8 @@ impl AvellanedaStoikov {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ self.update_dir();
|
|
|
+
|
|
|
let mut cci = self.cci_arc.lock().await;
|
|
|
cci.predictor_state_vec.push_back(PredictorState {
|
|
|
update_time: Decimal::from_i64(Utc::now().timestamp_millis()).unwrap(),
|
|
|
@@ -500,7 +558,7 @@ impl AvellanedaStoikov {
|
|
|
|
|
|
inventory: self.last_volume,
|
|
|
sigma_square: self.last_open_interest,
|
|
|
- gamma: self.flow_ratio_long,
|
|
|
+ gamma: self.dir,
|
|
|
kappa: self.t_diff,
|
|
|
|
|
|
flow_ratio: self.flow_ratio_long,
|