|
|
@@ -14,14 +14,12 @@ use standard::{Depth, Ticker, Trade};
|
|
|
#[derive(Debug)]
|
|
|
pub struct AvellanedaStoikov {
|
|
|
pub depth_vec: FixedTimeRangeDeque<Depth>, // 深度队列
|
|
|
- pub trade_long_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
- pub trade_short_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
+ pub trade_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
pub spread_vec: FixedTimeRangeDeque<Decimal>,
|
|
|
|
|
|
pub mid_price: Decimal, // 中间价
|
|
|
pub ask_price: Decimal, // 卖一价
|
|
|
pub bid_price: Decimal, // 买一价
|
|
|
- pub last_price: Decimal, // 最后成交价
|
|
|
pub spread: Decimal, // 市场冲击
|
|
|
pub spread_max: Decimal, // 最大市场冲击
|
|
|
pub spread_min: Decimal, // 最小市场冲击
|
|
|
@@ -29,54 +27,43 @@ pub struct AvellanedaStoikov {
|
|
|
pub optimal_bid_price: Decimal, // 买入挂单价
|
|
|
|
|
|
pub inventory: Decimal, // 库存,也就是q
|
|
|
- pub level: Decimal, // martin
|
|
|
pub sigma_square: Decimal, // σ^2,波动性的平方
|
|
|
pub gamma: Decimal, // γ,库存风险厌恶参数
|
|
|
pub kappa: Decimal, // κ 订单簿 流动性 参数
|
|
|
|
|
|
- pub flow_ratio_long: Decimal, // 资金流比例
|
|
|
- pub flow_ratio_short: Decimal, // 资金流比例
|
|
|
+ pub flow_in_value: Decimal,
|
|
|
+ pub flow_out_value: Decimal,
|
|
|
+ pub flow_ratio: Decimal, // 资金流比例
|
|
|
+ pub flow_ratio_diff_log: Decimal, // 一阶导数
|
|
|
|
|
|
- pub ask_delta: Decimal, // δa
|
|
|
- pub bid_delta: Decimal, // δb
|
|
|
- pub base_delta: Decimal, // 基础挂单距离
|
|
|
- pub ratio_edge: Decimal, // 资金流修正的挂单距离
|
|
|
+ pub delta_ask: Decimal, // δa
|
|
|
+ pub delta_bid: Decimal, // δb
|
|
|
pub ref_price: Decimal, // 预定价格
|
|
|
- pub init_delta_plus: Decimal, // 最初的delta之和
|
|
|
|
|
|
pub cci_arc: Arc<Mutex<CentralControlInfo>>, // 中控信息
|
|
|
|
|
|
pub is_ready: bool,
|
|
|
pub prev_trade_time: i64, // 上次交易时间,也就是t
|
|
|
- pub cross_time: i64, // 上次穿過0軸的時間
|
|
|
- pub cross_time_diff: i64, // 穿越0軸的diff
|
|
|
- pub cross_time_diff_avg: i64, // 穿越0軸的diff的平均值
|
|
|
pub t_diff: Decimal, // (T-t)
|
|
|
- pub prev_close_time: i64, // 上次平倉時間
|
|
|
- pub prev_prev_close_time: i64, // 上上次平倉時間
|
|
|
}
|
|
|
|
|
|
impl AvellanedaStoikov {
|
|
|
// 时间窗口大小(微秒)
|
|
|
- const MAX_TIME_RANGE_MICROS: i64 = 5 * 60_000_000;
|
|
|
- const TRADE_LONG_RANGE_MICROS: i64 = 3 * 60_000_000;
|
|
|
- const TRADE_SHORT_RANGE_MICROS: i64 = 20_000_000;
|
|
|
- // const ONE_MILLION: Decimal = dec!(1_000_000);
|
|
|
- // const TWENTY_THOUSAND: Decimal = dec!(20_000);
|
|
|
+ const MAX_TIME_RANGE_MICROS: i64 = 3 * 60_000_000;
|
|
|
+ const ONE_MILLION: Decimal = dec!(1_000_000);
|
|
|
+ const TWENTY_THOUSAND: Decimal = dec!(20_000);
|
|
|
const IRA: Decimal = dec!(1);
|
|
|
-
|
|
|
+
|
|
|
pub fn new(cci_arc: Arc<Mutex<CentralControlInfo>>) -> Self {
|
|
|
let avellaneda_stoikov = Self {
|
|
|
// 分别给与的长度
|
|
|
depth_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
|
|
|
+ trade_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
|
|
|
spread_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
|
|
|
- trade_long_vec: FixedTimeRangeDeque::new(Self::TRADE_LONG_RANGE_MICROS),
|
|
|
- trade_short_vec: FixedTimeRangeDeque::new(Self::TRADE_SHORT_RANGE_MICROS),
|
|
|
|
|
|
mid_price: Default::default(),
|
|
|
ask_price: Default::default(),
|
|
|
bid_price: Default::default(),
|
|
|
- last_price: Default::default(),
|
|
|
spread: Default::default(),
|
|
|
spread_max: Default::default(),
|
|
|
spread_min: Default::default(),
|
|
|
@@ -86,28 +73,20 @@ impl AvellanedaStoikov {
|
|
|
inventory: Default::default(),
|
|
|
gamma: Default::default(),
|
|
|
sigma_square: Default::default(),
|
|
|
- ask_delta: Default::default(),
|
|
|
- bid_delta: Default::default(),
|
|
|
- base_delta: Default::default(),
|
|
|
- init_delta_plus: Default::default(),
|
|
|
-
|
|
|
- ratio_edge: Default::default(),
|
|
|
+ delta_ask: Default::default(),
|
|
|
+ delta_bid: Default::default(),
|
|
|
kappa: Default::default(),
|
|
|
+ flow_in_value: Default::default(),
|
|
|
ref_price: Default::default(),
|
|
|
|
|
|
cci_arc,
|
|
|
|
|
|
is_ready: false,
|
|
|
- prev_trade_time: Utc::now().timestamp_micros(),
|
|
|
- cross_time: 0,
|
|
|
- cross_time_diff: 0,
|
|
|
- cross_time_diff_avg: 0,
|
|
|
+ prev_trade_time: 0,
|
|
|
t_diff: Default::default(),
|
|
|
- flow_ratio_long: Decimal::ONE,
|
|
|
- level: Default::default(),
|
|
|
- prev_close_time: Utc::now().timestamp_micros(),
|
|
|
- prev_prev_close_time: Utc::now().timestamp_micros(),
|
|
|
- flow_ratio_short: Default::default(),
|
|
|
+ flow_ratio: Decimal::ONE,
|
|
|
+ flow_ratio_diff_log: Default::default(),
|
|
|
+ flow_out_value: Default::default(),
|
|
|
};
|
|
|
|
|
|
avellaneda_stoikov
|
|
|
@@ -132,14 +111,14 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
pub fn update_spread(&mut self) {
|
|
|
- if self.trade_long_vec.len() > 0 {
|
|
|
+ if self.trade_vec.len() > 0 {
|
|
|
//
|
|
|
- let last_trade = self.trade_long_vec.get(self.trade_long_vec.len() - 1).unwrap();
|
|
|
+ let last_trade = self.trade_vec.get(self.trade_vec.len() - 1).unwrap();
|
|
|
let last_trade_price = last_trade.price;
|
|
|
let last_trade_time = last_trade.time;
|
|
|
|
|
|
let mut first_trade_price = last_trade.price;
|
|
|
- for trade in self.trade_long_vec.deque.iter().rev() {
|
|
|
+ for trade in self.trade_vec.deque.iter().rev() {
|
|
|
if last_trade_time - trade.time > Decimal::TEN {
|
|
|
break;
|
|
|
}
|
|
|
@@ -168,58 +147,84 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
pub async fn on_trade(&mut self, trade: &Trade) {
|
|
|
- self.trade_long_vec.push_back(trade.clone());
|
|
|
- self.trade_short_vec.push_back(trade.clone());
|
|
|
+ if trade.size > Decimal::ZERO {
|
|
|
+ self.flow_in_value += trade.value;
|
|
|
+ } else {
|
|
|
+ self.flow_out_value += trade.value;
|
|
|
+ }
|
|
|
+ if self.flow_in_value + self.flow_out_value > Self::ONE_MILLION {
|
|
|
+ self.flow_in_value = self.flow_in_value * dec!(0.618);
|
|
|
+ self.flow_out_value = self.flow_out_value * dec!(0.618);
|
|
|
+ }
|
|
|
|
|
|
- self.last_price = trade.price;
|
|
|
+ self.trade_vec.push_back(trade.clone());
|
|
|
self.update_spread();
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
- pub async fn update_level(&mut self) {
|
|
|
- self.level = (Decimal::NEGATIVE_ONE + (Decimal::ONE + dec!(8) * self.inventory.abs()).sqrt().unwrap()) / Decimal::TWO;
|
|
|
- self.level = min(self.level, dec!(6));
|
|
|
- }
|
|
|
+ pub async fn update_inventory(&mut self, inventory: &Decimal, step_size: &Decimal) {
|
|
|
+ let new_inventory = inventory / step_size;
|
|
|
+
|
|
|
+ if self.inventory.abs() < new_inventory.abs() {
|
|
|
+ self.prev_trade_time = Utc::now().timestamp_micros();
|
|
|
+ }
|
|
|
|
|
|
- pub async fn update_inventory(&mut self, inventory: &Decimal, min_amount_value: &Decimal) {
|
|
|
- self.prev_trade_time = Utc::now().timestamp_micros();
|
|
|
- self.inventory = (inventory / (min_amount_value / self.mid_price)).round();
|
|
|
+ self.inventory = new_inventory;
|
|
|
|
|
|
- // if self.inventory.is_zero() {
|
|
|
- // self.prev_prev_close_time = self.prev_close_time;
|
|
|
- // self.prev_close_time = Utc::now().timestamp_millis();
|
|
|
- // }
|
|
|
- self.update_level().await;
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
pub fn update_sigma_square(&mut self) {
|
|
|
- self.sigma_square = self.spread_max * dec!(1.618);
|
|
|
+ self.sigma_square = if self.trade_vec.len() < 2 {
|
|
|
+ Decimal::ZERO
|
|
|
+ } else {
|
|
|
+ let last_trade = self.trade_vec.get(self.trade_vec.len() - 1).unwrap();
|
|
|
+
|
|
|
+ let mut volatility_total = Decimal::ZERO;
|
|
|
+ for index in (0..self.trade_vec.len()).rev() {
|
|
|
+ if index == self.trade_vec.len() - 1 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ let trade = self.trade_vec.get(index).unwrap();
|
|
|
+
|
|
|
+ if last_trade.time - trade.time > Decimal::ONE_THOUSAND {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ let prev_trade = self.trade_vec.get(index + 1).unwrap();
|
|
|
+ let volatility = (trade.price - prev_trade.price).abs();
|
|
|
+ volatility_total += volatility;
|
|
|
+ }
|
|
|
+
|
|
|
+ volatility_total / Decimal::TEN
|
|
|
+ };
|
|
|
+
|
|
|
self.sigma_square.rescale(10);
|
|
|
}
|
|
|
|
|
|
pub fn update_gamma(&mut self) {
|
|
|
- // self.gamma = if self.sigma_square == Decimal::ZERO || self.inventory == Decimal::ZERO {
|
|
|
- // Decimal::ONE
|
|
|
- // } else {
|
|
|
- // Self::IRA * (self.spread_max - self.spread_min) / (Decimal::TWO * self.inventory.abs() * self.sigma_square)
|
|
|
- // };
|
|
|
- // self.gamma.rescale(8);
|
|
|
-
|
|
|
- self.gamma = dec!(1) * Self::IRA;
|
|
|
+ self.gamma = Decimal::ONE + Self::IRA * (self.spread_max / self.spread_min).sqrt().unwrap() / Decimal::TEN;
|
|
|
+ self.gamma.rescale(8);
|
|
|
}
|
|
|
|
|
|
pub fn update_kappa(&mut self) {
|
|
|
- // self.kappa = if self.spread_max.is_zero() || self.init_delta_plus.is_zero() {
|
|
|
- // Decimal::ONE
|
|
|
+ // if self.spread_max == Decimal::ZERO {
|
|
|
+ // self.kappa = Decimal::ONE;
|
|
|
// } else {
|
|
|
- // let mut temp = self.init_delta_plus * self.gamma - self.sigma_square * self.gamma.powd(Decimal::TWO);
|
|
|
- // temp.rescale(6);
|
|
|
+ // let delta_plus_max = (Decimal::TWO - Self::IRA) * self.spread_max + Self::IRA * self.spread_min;
|
|
|
+ // let mut temp = (delta_plus_max) * self.gamma - self.sigma_square * self.gamma.powd(Decimal::TWO);
|
|
|
//
|
|
|
- // self.gamma / (temp.exp() - Decimal::ONE)
|
|
|
- // };
|
|
|
+ // temp.rescale(6);
|
|
|
//
|
|
|
- // self.kappa.rescale(8);
|
|
|
+ // self.kappa = if temp <= Decimal::ZERO {
|
|
|
+ // Decimal::TEN
|
|
|
+ // } else if temp >= Decimal::TEN {
|
|
|
+ // Decimal::TEN
|
|
|
+ // } else {
|
|
|
+ // self.gamma / (temp.exp() - Decimal::ONE)
|
|
|
+ // };
|
|
|
+ // self.kappa.rescale(8);
|
|
|
+ // }
|
|
|
|
|
|
if self.mid_price > Decimal::ZERO {
|
|
|
self.kappa = dec!(888) / self.mid_price;
|
|
|
@@ -229,182 +234,73 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
pub fn update_ref_price(&mut self) {
|
|
|
- self.ref_price = self.mid_price;
|
|
|
+ self.ref_price = self.mid_price - self.inventory * self.gamma * self.sigma_square * self.t_diff;
|
|
|
}
|
|
|
|
|
|
pub fn update_delta(&mut self) {
|
|
|
- let pos_edge = self.gamma * self.sigma_square * self.inventory.abs().powd(Decimal::TWO) * self.t_diff;
|
|
|
-
|
|
|
- self.base_delta = self.sigma_square;
|
|
|
+ if self.gamma != Decimal::ZERO {
|
|
|
+ let a = (self.gamma * self.sigma_square * self.t_diff) / Decimal::TWO;
|
|
|
+ // let edge = (self.flow_ratio_diff_log.abs() / dec!(0.0003)) * self.gamma * self.sigma_square * self.t_diff;
|
|
|
|
|
|
- self.bid_delta = self.base_delta;
|
|
|
- self.ask_delta = self.base_delta;
|
|
|
+ self.delta_bid = {
|
|
|
+ let b = (Decimal::ONE / self.gamma) * (Decimal::ONE + self.gamma / self.kappa).ln();
|
|
|
|
|
|
- if self.inventory > Decimal::ZERO {
|
|
|
- self.bid_delta += pos_edge;
|
|
|
- } else if self.inventory < Decimal::ZERO {
|
|
|
- self.ask_delta += pos_edge;
|
|
|
- }
|
|
|
+ a + b
|
|
|
+ };
|
|
|
|
|
|
- if self.flow_ratio_long.is_zero() || self.cross_time_diff < 20 {
|
|
|
- self.ask_delta += self.base_delta;
|
|
|
- self.bid_delta += self.base_delta;
|
|
|
+ self.delta_ask = {
|
|
|
+ let b = (Decimal::ONE / self.gamma) * (Decimal::ONE + self.gamma / self.kappa).ln();
|
|
|
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if self.flow_ratio_long < Decimal::ZERO {
|
|
|
- if self.flow_ratio_short > Decimal::ZERO {
|
|
|
- self.ask_delta -= self.base_delta * (self.flow_ratio_short.abs() * Decimal::PI);
|
|
|
- self.bid_delta += self.base_delta;
|
|
|
- } else if self.flow_ratio_short < Decimal::ZERO && self.inventory < Decimal::ZERO {
|
|
|
- self.ask_delta += self.base_delta;
|
|
|
- // self.bid_delta -= self.base_delta * (self.flow_ratio_short.abs() + self.flow_ratio_long.abs());
|
|
|
- self.bid_delta -= self.base_delta * (self.flow_ratio_short.abs() * dec!(1.5));
|
|
|
- } else {
|
|
|
- self.ask_delta += self.base_delta;
|
|
|
- self.bid_delta += self.base_delta;
|
|
|
- }
|
|
|
- } else if self.flow_ratio_long > Decimal::ZERO {
|
|
|
- if self.flow_ratio_short > Decimal::ZERO && self.inventory > Decimal::ZERO {
|
|
|
- // self.ask_delta -= self.base_delta * (self.flow_ratio_short.abs() + self.flow_ratio_long.abs());
|
|
|
- self.ask_delta -= self.base_delta * (self.flow_ratio_short.abs() * dec!(1.5));
|
|
|
- self.bid_delta += self.base_delta;
|
|
|
- } else if self.flow_ratio_short < Decimal::ZERO {
|
|
|
- self.ask_delta += self.base_delta;
|
|
|
- self.bid_delta -= self.base_delta * (self.flow_ratio_short.abs() * Decimal::PI);
|
|
|
- } else {
|
|
|
- self.ask_delta += self.base_delta;
|
|
|
- self.bid_delta += self.base_delta;
|
|
|
- }
|
|
|
+ a + b
|
|
|
+ };
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pub fn update_optimal_ask_and_bid(&mut self) {
|
|
|
- self.optimal_ask_price = max(self.ref_price + self.ask_delta / dec!(2), self.ask_price);
|
|
|
- self.optimal_bid_price = min(self.ref_price - self.bid_delta / dec!(2), self.bid_price);
|
|
|
+ self.optimal_ask_price = max(self.ref_price + self.delta_ask / Decimal::TWO, self.ask_price);
|
|
|
+ self.optimal_bid_price = min(self.ref_price - self.delta_bid / Decimal::TWO, self.bid_price);
|
|
|
}
|
|
|
|
|
|
pub fn update_t_diff(&mut self) {
|
|
|
- if self.prev_trade_time > 0 {
|
|
|
- let time_diff_decimal = Decimal::from_i64(Utc::now().timestamp_micros() - self.prev_trade_time).unwrap();
|
|
|
- self.t_diff = max(Decimal::ONE - time_diff_decimal / Decimal::from_i64(Self::MAX_TIME_RANGE_MICROS).unwrap(), Decimal::ZERO);
|
|
|
- } else {
|
|
|
- self.t_diff = Decimal::ONE;
|
|
|
- }
|
|
|
+ // let time_diff_decimal = Decimal::from_i64(Utc::now().timestamp_micros() - self.prev_trade_time).unwrap();
|
|
|
+ // self.t_diff = time_diff_decimal / Decimal::from_i64(Self::MAX_TIME_RANGE_MICROS).unwrap();
|
|
|
+ // self.t_diff = min(self.t_diff, Decimal::ONE);
|
|
|
+ self.t_diff = Decimal::ONE;
|
|
|
}
|
|
|
|
|
|
- fn calc_flow_ratio(_prev_flow_ratio: &Decimal, min_volume: &Decimal, trades: &mut FixedTimeRangeDeque<Trade>) -> Decimal {
|
|
|
- // 使用EMA來更新資金流,確保平滑性
|
|
|
- // let a = Decimal::TWO / dec!(50);
|
|
|
-
|
|
|
- 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 * (prev_trade_iter.price - trade.price).abs();
|
|
|
- // flow_in_value += Decimal::ONE;
|
|
|
- } else if trade.price < prev_trade_iter.price {
|
|
|
- flow_out_value += trade.value * (prev_trade_iter.price - trade.price).abs();
|
|
|
- // flow_out_value += Decimal::ONE;
|
|
|
+ pub fn update_flow_ratio(&mut self) {
|
|
|
+ let prev_flow_ratio = self.flow_ratio;
|
|
|
+ self.flow_ratio = if self.trade_vec.len() < 2 {
|
|
|
+ Decimal::ZERO
|
|
|
+ } else {
|
|
|
+ if self.flow_out_value + self.flow_in_value <= Self::TWENTY_THOUSAND {
|
|
|
+ Decimal::ZERO
|
|
|
} else {
|
|
|
- // if trade.size > Decimal::ZERO {
|
|
|
- // flow_in_value += trade.value;
|
|
|
- // } else {
|
|
|
- // flow_out_value += trade.value;
|
|
|
- // }
|
|
|
+ self.flow_in_value / self.flow_out_value
|
|
|
}
|
|
|
+ };
|
|
|
|
|
|
- // if trade_iter.size > Decimal::ZERO {
|
|
|
- // flow_in_value += trade_iter.value;
|
|
|
- // } else {
|
|
|
- // flow_out_value += trade_iter.value;
|
|
|
- // }
|
|
|
- }
|
|
|
-
|
|
|
- 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 {
|
|
|
+ self.flow_ratio.rescale(6);
|
|
|
+ self.flow_ratio = if self.flow_ratio > Decimal::TEN {
|
|
|
Decimal::ZERO
|
|
|
- }
|
|
|
-
|
|
|
- // if self.trade_vec.deque.len() > 1 {
|
|
|
- // let prev_trade_iter = self.trade_vec.deque.get(self.trade_vec.deque.len() - 2).unwrap();
|
|
|
- // if trade.price > prev_trade_iter.price {
|
|
|
- // self.flow_in_value += trade.value;
|
|
|
- // } else if trade.price < prev_trade_iter.price {
|
|
|
- // self.flow_out_value += trade.value;
|
|
|
- // } else {
|
|
|
- // // if trade.size > Decimal::ZERO {
|
|
|
- // // self.flow_in_value += trade.value;
|
|
|
- // // } else {
|
|
|
- // // self.flow_out_value += trade.value;
|
|
|
- // // }
|
|
|
- // }
|
|
|
- //
|
|
|
- // // if trade.size > Decimal::ZERO {
|
|
|
- // // self.flow_in_value += trade.value;
|
|
|
- // // } else {
|
|
|
- // // self.flow_out_value += trade.value;
|
|
|
- // // }
|
|
|
- //
|
|
|
- // if self.flow_out_value + self.flow_in_value > dec!(2_000_000) {
|
|
|
- // self.flow_out_value = self.flow_out_value * dec!(0.618);
|
|
|
- // self.flow_in_value = self.flow_in_value * dec!(0.618);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // else {
|
|
|
- // if trade.size > Decimal::ZERO {
|
|
|
- // self.flow_in_value += trade.value;
|
|
|
- // } else {
|
|
|
- // self.flow_out_value += trade.value;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // self.flow_in_value = Decimal::ZERO;
|
|
|
- // self.flow_out_value = Decimal::ZERO;
|
|
|
- // for trade_iter in self.trade_vec.deque.iter() {
|
|
|
- // if trade_iter.size > Decimal::ZERO {
|
|
|
- // self.flow_in_value += trade_iter.value;
|
|
|
- // } else {
|
|
|
- // self.flow_out_value += trade_iter.value;
|
|
|
- // }
|
|
|
- // }
|
|
|
- }
|
|
|
+ } else if self.flow_ratio < dec!(-10) {
|
|
|
+ Decimal::ZERO
|
|
|
+ } else {
|
|
|
+ self.flow_ratio
|
|
|
+ };
|
|
|
|
|
|
- pub fn update_flow_ratio(&mut self) {
|
|
|
- let prev_flow_ratio_long = self.flow_ratio_long;
|
|
|
- self.flow_ratio_long = Self::calc_flow_ratio(&self.flow_ratio_long, &dec!(0), &mut self.trade_long_vec);
|
|
|
- let time = Utc::now().timestamp_millis();
|
|
|
- // let mut is_cross = false;
|
|
|
- if (self.flow_ratio_long > Decimal::ZERO && prev_flow_ratio_long <= Decimal::ZERO)
|
|
|
- || (self.flow_ratio_long < Decimal::ZERO && prev_flow_ratio_long >= Decimal::ZERO) {
|
|
|
- self.cross_time = time;
|
|
|
- // is_cross = true;
|
|
|
- }
|
|
|
+ if self.flow_ratio != Decimal::ZERO {
|
|
|
+ if prev_flow_ratio != Decimal::ZERO && self.flow_ratio != prev_flow_ratio {
|
|
|
+ let flow_ratio_diff = self.flow_ratio - prev_flow_ratio;
|
|
|
+ let temp = if flow_ratio_diff > Decimal::ZERO {
|
|
|
+ (flow_ratio_diff + Decimal::ONE).ln()
|
|
|
+ } else {
|
|
|
+ (flow_ratio_diff.abs() + Decimal::ONE).ln() * Decimal::NEGATIVE_ONE
|
|
|
+ };
|
|
|
|
|
|
- if self.cross_time != 0 {
|
|
|
- // let prev_cross_time_diff = self.cross_time_diff;
|
|
|
- self.cross_time_diff = (time - self.cross_time) / 1000;
|
|
|
-
|
|
|
- // if is_cross {
|
|
|
- // self.cross_time_diff_avg = if self.cross_time_diff_avg == 0 {
|
|
|
- // prev_cross_time_diff
|
|
|
- // } else {
|
|
|
- // (self.cross_time_diff_avg * 5 + prev_cross_time_diff * 5) / 10
|
|
|
- // };
|
|
|
- // }
|
|
|
+ self.flow_ratio_diff_log = temp * dec!(0.03) + self.flow_ratio_diff_log * dec!(0.97)
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- self.flow_ratio_short = Self::calc_flow_ratio(&self.flow_ratio_short, &dec!(0), &mut self.trade_short_vec);
|
|
|
}
|
|
|
|
|
|
pub fn check_ready(&mut self) {
|
|
|
@@ -424,11 +320,11 @@ impl AvellanedaStoikov {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if self.optimal_ask_price < self.ask_price {
|
|
|
+ if self.optimal_ask_price <= self.ask_price {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if self.optimal_bid_price > self.bid_price {
|
|
|
+ if self.optimal_bid_price >= self.bid_price {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -436,7 +332,7 @@ impl AvellanedaStoikov {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if self.trade_long_vec.len() < 100 {
|
|
|
+ if self.trade_vec.len() < 100 {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
@@ -472,23 +368,23 @@ impl AvellanedaStoikov {
|
|
|
cci.predictor_state_vec.push_back(PredictorState {
|
|
|
update_time: Decimal::from_i64(Utc::now().timestamp_millis()).unwrap(),
|
|
|
|
|
|
- mid_price: self.last_price,
|
|
|
+ mid_price: self.mid_price,
|
|
|
ask_price: self.ask_price,
|
|
|
bid_price: self.bid_price,
|
|
|
- last_price: self.last_price,
|
|
|
spread: self.spread,
|
|
|
- spread_max: self.ask_delta,
|
|
|
- spread_min: self.bid_delta,
|
|
|
+ spread_max: self.spread_max,
|
|
|
+ spread_min: self.spread_min,
|
|
|
optimal_ask_price: self.optimal_ask_price,
|
|
|
optimal_bid_price: self.optimal_bid_price,
|
|
|
|
|
|
inventory: self.inventory,
|
|
|
- sigma_square: self.flow_ratio_long,
|
|
|
- gamma: self.flow_ratio_short,
|
|
|
- kappa: Decimal::from(self.cross_time_diff),
|
|
|
+ sigma_square: self.sigma_square,
|
|
|
+ gamma: self.gamma,
|
|
|
+ kappa: self.kappa,
|
|
|
|
|
|
- flow_ratio: self.flow_ratio_long,
|
|
|
+ flow_ratio: self.flow_ratio_diff_log,
|
|
|
ref_price: self.ref_price,
|
|
|
+ last_price: self.mid_price,
|
|
|
});
|
|
|
}
|
|
|
|