|
|
@@ -45,6 +45,9 @@ pub struct AvellanedaStoikov {
|
|
|
|
|
|
pub flow_ratio: Decimal, // 资金流比例
|
|
|
pub money_flow_index: Decimal, // MFI
|
|
|
+ pub long_trade_len_dec: Decimal,
|
|
|
+ pub short_trade_len_dec: Decimal,
|
|
|
+ pub error_rate: Decimal, // 犯错概率(预估)
|
|
|
|
|
|
pub ask_delta: Decimal, // δa
|
|
|
pub bid_delta: Decimal, // δb
|
|
|
@@ -57,6 +60,8 @@ pub struct AvellanedaStoikov {
|
|
|
pub is_ready: bool,
|
|
|
pub prev_trade_time: i64, // 上次交易时间,也就是t
|
|
|
pub t_diff: Decimal, // (T-t)
|
|
|
+ pub last_update_time: Decimal,
|
|
|
+ pub last_index: Decimal,
|
|
|
}
|
|
|
|
|
|
impl AvellanedaStoikov {
|
|
|
@@ -117,6 +122,11 @@ impl AvellanedaStoikov {
|
|
|
flow_ratio: Default::default(),
|
|
|
money_flow_index: Default::default(),
|
|
|
pos_amount: Default::default(),
|
|
|
+ error_rate: Default::default(),
|
|
|
+ long_trade_len_dec: Default::default(),
|
|
|
+ short_trade_len_dec: Default::default(),
|
|
|
+ last_update_time: Default::default(),
|
|
|
+ last_index: Default::default(),
|
|
|
};
|
|
|
|
|
|
avellaneda_stoikov
|
|
|
@@ -198,6 +208,8 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
pub async fn on_depth(&mut self, depth: &Depth, index: usize) {
|
|
|
+ self.last_update_time = depth.time;
|
|
|
+ self.last_index = Decimal::from(index);
|
|
|
self.update_fair_price(depth, index).await;
|
|
|
|
|
|
if index == 0 {
|
|
|
@@ -212,10 +224,17 @@ impl AvellanedaStoikov {
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
- pub async fn on_trade(&mut self, trade: &Trade) {
|
|
|
+ pub async fn on_trade(&mut self, trade: &Trade, _index: usize) {
|
|
|
+ // self.last_update_time = trade.time;
|
|
|
+
|
|
|
self.trade_long_vec.push_back(trade.clone());
|
|
|
self.trade_short_vec.push_back(trade.clone());
|
|
|
|
|
|
+ self.long_trade_len_dec = Decimal::from_usize(self.trade_long_vec.len()).unwrap();
|
|
|
+ self.short_trade_len_dec = Decimal::from_usize(self.trade_short_vec.len()).unwrap();
|
|
|
+ self.error_rate = self.short_trade_len_dec / self.long_trade_len_dec;
|
|
|
+ self.error_rate.rescale(4);
|
|
|
+
|
|
|
self.last_price = trade.price;
|
|
|
self.processor().await;
|
|
|
}
|
|
|
@@ -298,7 +317,7 @@ impl AvellanedaStoikov {
|
|
|
self.update_flow_ratio();
|
|
|
}
|
|
|
|
|
|
- pub async fn update_inventory(&mut self, pos_amount: &Decimal, min_amount_value: &Decimal) {
|
|
|
+ pub async fn on_inventory(&mut self, pos_amount: &Decimal, min_amount_value: &Decimal) {
|
|
|
let prev_inventory = self.inventory;
|
|
|
self.pos_amount = pos_amount.clone();
|
|
|
self.inventory = (pos_amount / (min_amount_value / self.mid_price)).floor();
|
|
|
@@ -329,19 +348,19 @@ impl AvellanedaStoikov {
|
|
|
|
|
|
pub fn update_ref_price(&mut self) {
|
|
|
if !self.fair_price_vec[0].is_zero() && !self.fair_price_vec[1].is_zero() {
|
|
|
- let v0_rate = self.volume_vec[0] / (self.volume_vec[0] + self.volume_vec[1]);
|
|
|
- let v1_rate = self.volume_vec[1] / (self.volume_vec[0] + self.volume_vec[1]);
|
|
|
-
|
|
|
- let sma = self.depth_vec[1].asks[0].price;
|
|
|
- let smb = self.depth_vec[1].bids[0].price;
|
|
|
-
|
|
|
- let mp0 = self.mid_price;
|
|
|
- let mp1 = (sma + smb) / Decimal::TWO;
|
|
|
+ // let v0_rate = self.volume_vec[0] / (self.volume_vec[0] + self.volume_vec[1]);
|
|
|
+ // let v1_rate = self.volume_vec[1] / (self.volume_vec[0] + self.volume_vec[1]);
|
|
|
|
|
|
- let price_diff = mp0 - mp1;
|
|
|
+ // let sma = self.depth_vec[1].asks[0].price;
|
|
|
+ // let smb = self.depth_vec[1].bids[0].price;
|
|
|
+ //
|
|
|
+ // let mp0 = self.mid_price;
|
|
|
+ // let mp1 = (sma + smb) / Decimal::TWO;
|
|
|
+ //
|
|
|
+ // let price_diff = mp0 - mp1;
|
|
|
|
|
|
- self.ref_price = (self.fair_price_vec[0] + self.fair_price_vec[1] + price_diff) / Decimal::TWO;
|
|
|
- // self.ref_price = (self.fair_price_vec[0] + self.fair_price_vec[1]) / Decimal::TWO;
|
|
|
+ // self.ref_price = (self.fair_price_vec[0] + self.fair_price_vec[1] + price_diff) / Decimal::TWO;
|
|
|
+ self.ref_price = (self.fair_price_vec[0] + self.fair_price_vec[1]) / Decimal::TWO;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -354,7 +373,7 @@ impl AvellanedaStoikov {
|
|
|
self.bid_delta = self.base_delta * Decimal::TWO;
|
|
|
self.ask_delta = self.base_delta;
|
|
|
|
|
|
- if self.money_flow_index < dec!(50) {
|
|
|
+ if self.money_flow_index < dec!(50) && self.error_rate > dec!(0.3) {
|
|
|
self.bid_delta = self.base_delta;
|
|
|
}
|
|
|
|
|
|
@@ -474,20 +493,18 @@ impl AvellanedaStoikov {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- let mut cci = self.cci_arc.lock().await;
|
|
|
let mut smm = Decimal::ZERO;
|
|
|
if !self.depth_vec[1].time.is_zero() {
|
|
|
let sma = self.depth_vec[1].asks[0].price;
|
|
|
let smb = self.depth_vec[1].bids[0].price;
|
|
|
smm = (sma + smb) / Decimal::TWO;
|
|
|
}
|
|
|
- let short_len = Decimal::from_usize(self.trade_short_vec.len()).unwrap();
|
|
|
- let long_len = Decimal::from_usize(self.trade_long_vec.len()).unwrap();
|
|
|
- let mut rate = short_len / long_len;
|
|
|
- rate.rescale(4);
|
|
|
|
|
|
+ let now = Decimal::from_i64(Utc::now().timestamp_millis()).unwrap();
|
|
|
+
|
|
|
+ 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(),
|
|
|
+ update_time: now,
|
|
|
|
|
|
mid_price: self.last_price,
|
|
|
ask_price: self.ask_price,
|
|
|
@@ -500,9 +517,9 @@ impl AvellanedaStoikov {
|
|
|
optimal_bid_price: self.optimal_bid_price,
|
|
|
|
|
|
inventory: self.inventory,
|
|
|
- sigma_square: rate,
|
|
|
- gamma: short_len,
|
|
|
- kappa: long_len,
|
|
|
+ sigma_square: self.error_rate,
|
|
|
+ gamma: now - self.last_update_time,
|
|
|
+ kappa: self.last_index,
|
|
|
|
|
|
flow_ratio: Decimal::ZERO,
|
|
|
ref_price: self.ref_price,
|