|
|
@@ -37,13 +37,13 @@ pub struct AvellanedaStoikov {
|
|
|
|
|
|
pub flow_ratio_long: Decimal, // 资金流比例
|
|
|
pub flow_ratio_short: Decimal, // 资金流比例
|
|
|
+ pub money_flow_index: Decimal, // MFI
|
|
|
|
|
|
pub ask_delta: Decimal, // δa
|
|
|
pub bid_delta: Decimal, // δb
|
|
|
pub base_delta: Decimal, // 基础挂单距离
|
|
|
pub ratio_edge: Decimal, // 资金流修正的挂单距离
|
|
|
pub ref_price: Decimal, // 预定价格
|
|
|
- pub init_delta_plus: Decimal, // 最初的delta之和
|
|
|
|
|
|
pub cci_arc: Arc<Mutex<CentralControlInfo>>, // 中控信息
|
|
|
|
|
|
@@ -87,7 +87,6 @@ impl AvellanedaStoikov {
|
|
|
ask_delta: Default::default(),
|
|
|
bid_delta: Default::default(),
|
|
|
base_delta: Default::default(),
|
|
|
- init_delta_plus: Default::default(),
|
|
|
|
|
|
ratio_edge: Default::default(),
|
|
|
kappa: Default::default(),
|
|
|
@@ -98,9 +97,10 @@ impl AvellanedaStoikov {
|
|
|
is_ready: false,
|
|
|
prev_trade_time: Utc::now().timestamp_micros(),
|
|
|
t_diff: Default::default(),
|
|
|
- flow_ratio_long: Decimal::ONE,
|
|
|
level: Default::default(),
|
|
|
+ flow_ratio_long: Default::default(),
|
|
|
flow_ratio_short: Default::default(),
|
|
|
+ money_flow_index: Default::default(),
|
|
|
};
|
|
|
|
|
|
avellaneda_stoikov
|
|
|
@@ -189,6 +189,35 @@ impl AvellanedaStoikov {
|
|
|
self.record_vec.push_back(record.clone());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 如果蜡烛数量足够,则更新mfi
|
|
|
+ if self.record_vec.len() >= 3 {
|
|
|
+ self.update_mfi();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn update_mfi(&mut self) {
|
|
|
+ let mut money_flow_in = Decimal::ZERO;
|
|
|
+ let mut money_flow_out = Decimal::ZERO;
|
|
|
+ let _3 = dec!(3);
|
|
|
+
|
|
|
+ for record in self.record_vec.deque.iter() {
|
|
|
+ let typical_price = (record.high + record.low + record.close) / _3;
|
|
|
+ let money_flow = typical_price * record.volume;
|
|
|
+ if record.close > record.open {
|
|
|
+ money_flow_in += money_flow;
|
|
|
+ } else if record.close < record.open {
|
|
|
+ money_flow_out += money_flow;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ self.money_flow_index = if money_flow_out.is_zero() {
|
|
|
+ Decimal::ONE_HUNDRED
|
|
|
+ } else {
|
|
|
+ let money_flow_ratio = money_flow_in / money_flow_out;
|
|
|
+
|
|
|
+ Decimal::ONE_HUNDRED - Decimal::ONE_HUNDRED / (Decimal::ONE + money_flow_ratio)
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
pub async fn update_inventory(&mut self, inventory: &Decimal, min_amount_value: &Decimal) {
|
|
|
@@ -264,10 +293,6 @@ impl AvellanedaStoikov {
|
|
|
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);
|
|
|
}
|
|
|
-
|
|
|
- if self.init_delta_plus.is_zero() {
|
|
|
- self.init_delta_plus = (self.bid_delta + self.ask_delta) / Decimal::TWO
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -487,8 +512,8 @@ impl AvellanedaStoikov {
|
|
|
optimal_bid_price: self.optimal_bid_price,
|
|
|
|
|
|
inventory: self.inventory,
|
|
|
- sigma_square: self.flow_ratio_long,
|
|
|
- gamma: self.flow_ratio_short,
|
|
|
+ sigma_square: self.money_flow_index,
|
|
|
+ gamma: self.flow_ratio_long,
|
|
|
kappa: self.t_diff,
|
|
|
|
|
|
flow_ratio: self.flow_ratio_long,
|