|
|
@@ -35,7 +35,7 @@ pub struct AvellanedaStoikov {
|
|
|
pub gamma: Decimal, // γ,库存风险厌恶参数
|
|
|
pub kappa: Decimal, // κ 订单簿 流动性 参数
|
|
|
|
|
|
- pub flow_ratio_long: Decimal, // 资金流比例
|
|
|
+ pub flow_ratio: Decimal, // 资金流比例
|
|
|
pub flow_ratio_short: Decimal, // 资金流比例
|
|
|
pub money_flow_index: Decimal, // MFI
|
|
|
|
|
|
@@ -98,7 +98,7 @@ impl AvellanedaStoikov {
|
|
|
prev_trade_time: Utc::now().timestamp_micros(),
|
|
|
t_diff: Default::default(),
|
|
|
level: Default::default(),
|
|
|
- flow_ratio_long: Default::default(),
|
|
|
+ flow_ratio: Default::default(),
|
|
|
flow_ratio_short: Default::default(),
|
|
|
money_flow_index: Default::default(),
|
|
|
};
|
|
|
@@ -275,7 +275,7 @@ impl AvellanedaStoikov {
|
|
|
let pos_edge = self.gamma * self.sigma_square * self.inventory.abs().powd(dec!(2)) * self.t_diff;
|
|
|
|
|
|
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_long * self.sigma_square;
|
|
|
+ self.ratio_edge = self.flow_ratio * self.sigma_square;
|
|
|
|
|
|
self.bid_delta = self.base_delta;
|
|
|
self.ask_delta = self.base_delta;
|
|
|
@@ -287,11 +287,14 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
if self.ratio_edge > Decimal::ZERO {
|
|
|
- self.ask_delta = self.ask_delta - self.ratio_edge.abs() * (Decimal::TWO - self.t_diff);
|
|
|
- self.bid_delta = self.bid_delta + self.ratio_edge.abs() * dec!(16);
|
|
|
+ self.ask_delta -= self.ratio_edge.abs() * (Decimal::TWO - self.t_diff);
|
|
|
+ self.bid_delta += self.ratio_edge.abs() * dec!(16);
|
|
|
} else if self.ratio_edge < Decimal::ZERO {
|
|
|
- self.ask_delta = self.ask_delta + self.ratio_edge.abs() * dec!(16);
|
|
|
- self.bid_delta = self.bid_delta - self.ratio_edge.abs() * (Decimal::TWO - self.t_diff);
|
|
|
+ self.ask_delta += self.ratio_edge.abs() * dec!(16);
|
|
|
+ self.bid_delta -= self.ratio_edge.abs() * (Decimal::TWO - self.t_diff);
|
|
|
+ } else if self.ratio_edge == Decimal::ZERO {
|
|
|
+ self.ask_delta += self.sigma_square.abs() * dec!(5);
|
|
|
+ self.bid_delta += self.sigma_square.abs() * dec!(5);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -395,44 +398,50 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fn calc_flow_ratio_2(_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;
|
|
|
- // flow_in_value += Decimal::ONE;
|
|
|
- } else if trade.price < prev_trade_iter.price {
|
|
|
- flow_out_value += trade.value;
|
|
|
- // flow_out_value += Decimal::ONE;
|
|
|
- } else {
|
|
|
- if trade.size > Decimal::ZERO {
|
|
|
- flow_in_value += trade.value;
|
|
|
- } else {
|
|
|
- flow_out_value += trade.value;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ // fn calc_flow_ratio_2(_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;
|
|
|
+ // // flow_in_value += Decimal::ONE;
|
|
|
+ // } else if trade.price < prev_trade_iter.price {
|
|
|
+ // flow_out_value += trade.value;
|
|
|
+ // // flow_out_value += Decimal::ONE;
|
|
|
+ // } else {
|
|
|
+ // if trade.size > Decimal::ZERO {
|
|
|
+ // flow_in_value += trade.value;
|
|
|
+ // } else {
|
|
|
+ // flow_out_value += trade.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 {
|
|
|
+ // Decimal::ZERO
|
|
|
+ // }
|
|
|
+ // }
|
|
|
|
|
|
- // 使用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)
|
|
|
+ pub fn update_flow_ratio(&mut self) {
|
|
|
+ self.flow_ratio = if self.money_flow_index > dec!(80) {
|
|
|
+ (self.money_flow_index - dec!(80)) / dec!(20)
|
|
|
+ } else if self.money_flow_index < dec!(20) {
|
|
|
+ Decimal::NEGATIVE_ONE * self.money_flow_index / dec!(20)
|
|
|
} else {
|
|
|
Decimal::ZERO
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pub fn update_flow_ratio(&mut self) {
|
|
|
- self.flow_ratio_long = Self::calc_flow_ratio_2(&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_long_vec);
|
|
|
}
|
|
|
|
|
|
@@ -513,10 +522,10 @@ impl AvellanedaStoikov {
|
|
|
|
|
|
inventory: self.inventory,
|
|
|
sigma_square: self.money_flow_index,
|
|
|
- gamma: self.flow_ratio_long,
|
|
|
+ gamma: self.flow_ratio,
|
|
|
kappa: self.t_diff,
|
|
|
|
|
|
- flow_ratio: self.flow_ratio_long,
|
|
|
+ flow_ratio: self.flow_ratio,
|
|
|
ref_price: self.ref_price,
|
|
|
});
|
|
|
}
|