|
|
@@ -16,7 +16,10 @@ pub struct AvellanedaStoikov {
|
|
|
pub depth_vec: FixedTimeRangeDeque<Depth>, // 深度队列
|
|
|
pub trade_long_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
pub trade_short_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
+ pub open_interest_vec: FixedTimeRangeDeque<Decimal>, // OpenInterest队列
|
|
|
+ pub ticker_vec: FixedTimeRangeDeque<Ticker>, // Ticker队列
|
|
|
pub spread_vec: FixedTimeRangeDeque<Decimal>,
|
|
|
+ pub money_flow_vec: FixedTimeRangeDeque<Decimal>, // MoneyFlow队列
|
|
|
|
|
|
pub mid_price: Decimal, // 中间价
|
|
|
pub ask_price: Decimal, // 卖一价
|
|
|
@@ -34,15 +37,19 @@ pub struct AvellanedaStoikov {
|
|
|
pub gamma: Decimal, // γ,库存风险厌恶参数
|
|
|
pub kappa: Decimal, // κ 订单簿 流动性 参数
|
|
|
|
|
|
- pub flow_ratio_long: Decimal, // 资金流比例
|
|
|
- pub flow_ratio_short: Decimal, // 资金流比例
|
|
|
+ pub open_interest: Decimal, // 最后持仓量
|
|
|
+ pub open_interest_ema: Decimal, // 持仓量的ema
|
|
|
+ pub open_interest_diff: Decimal, // 持仓量与ema的diff
|
|
|
+ pub money_flow: Decimal, // 资金流
|
|
|
+ pub money_flow_ema: Decimal, // 资金流ema
|
|
|
+ pub money_flow_diff: Decimal, // 资金流差值
|
|
|
+ pub money_flow_prev_cross: Decimal, // 资金量上次穿越0轴时的价格
|
|
|
+ pub total_cross_diff: Decimal, // 总共的穿越和(理论利润)
|
|
|
|
|
|
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>>, // 中控信息
|
|
|
|
|
|
@@ -55,7 +62,7 @@ impl AvellanedaStoikov {
|
|
|
// 时间窗口大小(微秒)
|
|
|
const MAX_TIME_RANGE_MICROS: i64 = 3 * 60_000_000;
|
|
|
const TRADE_LONG_RANGE_MICROS: i64 = 3 * 60_000_000;
|
|
|
- const TRADE_SHORT_RANGE_MICROS: i64 = 20_000_000;
|
|
|
+ const TRADE_SHORT_RANGE_MICROS: i64 = 60_000_000;
|
|
|
// const ONE_MILLION: Decimal = dec!(1_000_000);
|
|
|
// const TWENTY_THOUSAND: Decimal = dec!(20_000);
|
|
|
const IRA: Decimal = dec!(1);
|
|
|
@@ -66,7 +73,10 @@ impl AvellanedaStoikov {
|
|
|
depth_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),
|
|
|
+ ticker_vec: FixedTimeRangeDeque::new(Self::TRADE_LONG_RANGE_MICROS),
|
|
|
trade_short_vec: FixedTimeRangeDeque::new(Self::TRADE_SHORT_RANGE_MICROS),
|
|
|
+ open_interest_vec: FixedTimeRangeDeque::new(Self::TRADE_SHORT_RANGE_MICROS),
|
|
|
+ money_flow_vec: FixedTimeRangeDeque::new(Self::TRADE_LONG_RANGE_MICROS),
|
|
|
|
|
|
mid_price: Default::default(),
|
|
|
ask_price: Default::default(),
|
|
|
@@ -84,20 +94,25 @@ 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(),
|
|
|
ref_price: Default::default(),
|
|
|
|
|
|
cci_arc,
|
|
|
|
|
|
+ money_flow: Default::default(),
|
|
|
+ money_flow_ema: Default::default(),
|
|
|
+ money_flow_diff: Default::default(),
|
|
|
+ money_flow_prev_cross: Default::default(),
|
|
|
+ open_interest: Default::default(),
|
|
|
+ open_interest_ema: Default::default(),
|
|
|
+ open_interest_diff: Default::default(),
|
|
|
+
|
|
|
is_ready: false,
|
|
|
prev_trade_time: Utc::now().timestamp_micros(),
|
|
|
t_diff: Default::default(),
|
|
|
- flow_ratio_long: Decimal::ONE,
|
|
|
level: Default::default(),
|
|
|
- flow_ratio_short: Default::default(),
|
|
|
+ total_cross_diff: Default::default(),
|
|
|
};
|
|
|
|
|
|
avellaneda_stoikov
|
|
|
@@ -157,12 +172,219 @@ impl AvellanedaStoikov {
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
+ // fn calc_flow_ratio(_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 trade_iter in trades.deque.iter() {
|
|
|
+ // if trade_iter.size > Decimal::ZERO {
|
|
|
+ // flow_in_value += trade_iter.value;
|
|
|
+ // } else {
|
|
|
+ // flow_out_value += trade_iter.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
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //
|
|
|
+ // 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
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 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);
|
|
|
+ // }
|
|
|
+
|
|
|
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());
|
|
|
|
|
|
self.last_price = trade.price;
|
|
|
self.update_spread();
|
|
|
+ // self.update_flow_ratio();
|
|
|
+ self.processor().await;
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn update_money_flow(&mut self) {
|
|
|
+ // ====================== 求最大值,最小值。方便后面进行0-1标准化 =======================
|
|
|
+ let mut max_price_diff = Decimal::MIN;
|
|
|
+ let mut min_price_diff = Decimal::MAX;
|
|
|
+
|
|
|
+ let mut max_open_interest_diff = Decimal::MIN;
|
|
|
+ let mut min_open_interest_diff = Decimal::MAX;
|
|
|
+ for (index, ticker) in self.ticker_vec.deque.iter().enumerate() {
|
|
|
+ if index == 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ let prev_ticker = self.ticker_vec.deque.get(index - 1).unwrap();
|
|
|
+ let price_diff = (ticker.last - prev_ticker.last).abs();
|
|
|
+ let open_interest_diff = (ticker.open_interest - prev_ticker.open_interest).abs();
|
|
|
+
|
|
|
+ max_price_diff = max(max_price_diff, price_diff);
|
|
|
+ min_price_diff = min(min_price_diff, price_diff);
|
|
|
+
|
|
|
+ max_open_interest_diff = max(max_open_interest_diff, open_interest_diff);
|
|
|
+ min_open_interest_diff = min(min_open_interest_diff, open_interest_diff);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ====================== 求资金流 =======================
|
|
|
+ // self.money_flow = Decimal::ZERO;
|
|
|
+ let epsilon = dec!(1e-10);
|
|
|
+ // for (index, ticker) in self.ticker_vec.deque.iter().enumerate() {
|
|
|
+ if self.ticker_vec.len() < 2 {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 当前的diff(abs)
|
|
|
+ let ticker = self.ticker_vec.deque.get(self.ticker_vec.len() - 1).unwrap();
|
|
|
+ let prev_ticker = self.ticker_vec.deque.get( self.ticker_vec.len() - 2).unwrap();
|
|
|
+ let price_diff = ticker.last - prev_ticker.last;
|
|
|
+ let price_diff_abs = price_diff.abs();
|
|
|
+ let open_interest_diff = ticker.open_interest - prev_ticker.open_interest;
|
|
|
+ let open_interest_diff_abs = open_interest_diff.abs();
|
|
|
+ let volume_diff = max(ticker.volume - prev_ticker.volume, Decimal::ZERO);
|
|
|
+
|
|
|
+ // 0-1标准化
|
|
|
+ let price_std = if max_price_diff == min_price_diff {
|
|
|
+ Decimal::ZERO
|
|
|
+ } else {
|
|
|
+ (price_diff_abs - min_price_diff) / (max_price_diff - min_price_diff)
|
|
|
+ };
|
|
|
+ let open_interest_std = if max_open_interest_diff == min_open_interest_diff {
|
|
|
+ Decimal::ZERO
|
|
|
+ } else {
|
|
|
+ (open_interest_diff_abs - min_open_interest_diff) / (max_open_interest_diff - min_open_interest_diff)
|
|
|
+ };
|
|
|
+
|
|
|
+ // alpha与beta
|
|
|
+ // 当α>β时,表明价格变动对资金流向的影响更大,此时市场可能处于较强的买入状态,反映出资金流入的趋势。
|
|
|
+ // 当α<β时,持仓量的变动对资金流向影响更大,可能暗示资金的卖出或清算过程。
|
|
|
+ let alpha = (price_std + epsilon) / (price_std + open_interest_std + epsilon + epsilon);
|
|
|
+ let beta = (open_interest_std + epsilon) / (price_std + open_interest_std + epsilon + epsilon);
|
|
|
+
|
|
|
+ // 求x,为sgn(x)做准备
|
|
|
+ let x = if !price_diff_abs.is_zero() && !open_interest_diff_abs.is_zero() {
|
|
|
+ alpha * price_diff / price_diff_abs + beta * open_interest_diff / open_interest_diff_abs
|
|
|
+ } else if price_diff_abs.is_zero() && open_interest_diff_abs.is_zero() {
|
|
|
+ Decimal::ZERO
|
|
|
+ } else if price_diff_abs.is_zero() && !open_interest_diff_abs.is_zero() {
|
|
|
+ beta * open_interest_diff / open_interest_diff_abs
|
|
|
+ } else {
|
|
|
+ alpha * price_diff / price_diff_abs
|
|
|
+ };
|
|
|
+
|
|
|
+ // 求xgn(x)
|
|
|
+ let sgn_x = if x > Decimal::ZERO {
|
|
|
+ Decimal::ONE
|
|
|
+ } else if x < Decimal::ZERO {
|
|
|
+ Decimal::NEGATIVE_ONE
|
|
|
+ } else {
|
|
|
+ Decimal::ZERO
|
|
|
+ };
|
|
|
+
|
|
|
+ // 当前index的money_flow
|
|
|
+ let money_flow_index = volume_diff * ticker.last * sgn_x;
|
|
|
+ self.money_flow += money_flow_index;
|
|
|
+ self.money_flow_vec.push_back(self.money_flow);
|
|
|
+ if !money_flow_index.is_zero() {
|
|
|
+ self.money_flow_ema = if self.money_flow_ema.is_zero() {
|
|
|
+ self.money_flow
|
|
|
+ } else {
|
|
|
+ dec!(0.01) * self.money_flow + dec!(0.99) * self.money_flow_ema
|
|
|
+ };
|
|
|
+
|
|
|
+ let prev_money_flow_diff = self.money_flow_diff;
|
|
|
+ self.money_flow_diff = self.money_flow - self.money_flow_ema;
|
|
|
+
|
|
|
+ let _0 = Decimal::ZERO;
|
|
|
+ let is_cross = (prev_money_flow_diff > _0 && self.money_flow_diff < _0) || (prev_money_flow_diff < _0 && self.money_flow_diff > _0);
|
|
|
+ if is_cross {
|
|
|
+ if !self.money_flow_prev_cross.is_zero() {
|
|
|
+ if prev_money_flow_diff > _0 {
|
|
|
+ self.total_cross_diff += self.mid_price - self.money_flow_prev_cross;
|
|
|
+ } else {
|
|
|
+ self.total_cross_diff += self.money_flow_prev_cross - self.mid_price;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ self.money_flow_prev_cross = self.mid_price;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn on_ticker(&mut self, ticker: &Ticker) {
|
|
|
+ if self.open_interest_vec.len() > 0 {
|
|
|
+ let diff = ticker.open_interest - self.open_interest_vec.get(0).unwrap();
|
|
|
+ self.open_interest_diff = if diff.is_zero() {
|
|
|
+ self.open_interest_diff
|
|
|
+ } else {
|
|
|
+ if diff > Decimal::ZERO {
|
|
|
+ Decimal::ONE
|
|
|
+ } else {
|
|
|
+ Decimal::NEGATIVE_ONE
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+ self.open_interest_vec.push_back(ticker.open_interest.clone());
|
|
|
+ self.ticker_vec.push_back(ticker.clone());
|
|
|
+
|
|
|
+ self.last_price = ticker.last;
|
|
|
+ self.ask_price = ticker.sell;
|
|
|
+ self.bid_price = ticker.buy;
|
|
|
+ self.mid_price = (self.ask_price + self.bid_price) / Decimal::TWO;
|
|
|
+ // 持仓量的处理
|
|
|
+ if self.open_interest != ticker.open_interest {
|
|
|
+ self.open_interest = ticker.open_interest;
|
|
|
+ self.open_interest_ema = if self.open_interest_ema.is_zero() {
|
|
|
+ self.open_interest
|
|
|
+ } else {
|
|
|
+ dec!(0.5) * self.open_interest + dec!(0.5) * self.open_interest_ema
|
|
|
+ };
|
|
|
+ }
|
|
|
+ self.open_interest_diff = self.open_interest - self.open_interest_ema;
|
|
|
+
|
|
|
+ self.update_money_flow();
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
@@ -183,7 +405,7 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
|
|
|
pub fn update_sigma_square(&mut self) {
|
|
|
- self.sigma_square = self.spread_max * dec!(0.5);
|
|
|
+ self.sigma_square = self.spread_max;
|
|
|
self.sigma_square.rescale(10);
|
|
|
}
|
|
|
|
|
|
@@ -223,15 +445,9 @@ impl AvellanedaStoikov {
|
|
|
|
|
|
pub fn update_delta(&mut self) {
|
|
|
if self.gamma != Decimal::ZERO {
|
|
|
- // let pos_edge = if self.inventory.abs() < dec!(5) {
|
|
|
- // self.gamma * self.sigma_square * self.inventory.abs().powd(Decimal::TWO) * self.t_diff
|
|
|
- // } else {
|
|
|
- // Decimal::PI * self.gamma * self.sigma_square * self.inventory.abs().powd(Decimal::TWO) * self.t_diff
|
|
|
- // };
|
|
|
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.bid_delta = self.base_delta;
|
|
|
self.ask_delta = self.base_delta;
|
|
|
@@ -242,16 +458,12 @@ impl AvellanedaStoikov {
|
|
|
self.ask_delta += pos_edge;
|
|
|
}
|
|
|
|
|
|
- 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);
|
|
|
- } 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);
|
|
|
- }
|
|
|
-
|
|
|
- if self.init_delta_plus.is_zero() {
|
|
|
- self.init_delta_plus = (self.bid_delta + self.ask_delta) / Decimal::TWO
|
|
|
+ if self.money_flow_diff > Decimal::ZERO {
|
|
|
+ self.ask_delta -= self.base_delta * (Decimal::TWO - self.t_diff);
|
|
|
+ self.bid_delta += self.base_delta;
|
|
|
+ } else if self.money_flow_diff < Decimal::ZERO {
|
|
|
+ self.ask_delta += self.base_delta;
|
|
|
+ self.bid_delta -= self.base_delta * (Decimal::TWO - self.t_diff);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -270,132 +482,6 @@ impl AvellanedaStoikov {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fn calc_flow_ratio(_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 * (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;
|
|
|
- // } else {
|
|
|
- // // if trade.size > Decimal::ZERO {
|
|
|
- // // flow_in_value += trade.value;
|
|
|
- // // } else {
|
|
|
- // // flow_out_value += trade.value;
|
|
|
- // // }
|
|
|
- // }
|
|
|
- //
|
|
|
- // // if trade_iter.size > Decimal::ZERO {
|
|
|
- // // flow_in_value += trade_iter.value;
|
|
|
- // // } else {
|
|
|
- // // flow_out_value += trade_iter.value;
|
|
|
- // // }
|
|
|
- // }
|
|
|
-
|
|
|
- // 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;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- let mut flow_in_value = Decimal::ZERO;
|
|
|
- let mut flow_out_value = Decimal::ZERO;
|
|
|
- for trade_iter in trades.deque.iter() {
|
|
|
- if trade_iter.size > Decimal::ZERO {
|
|
|
- flow_in_value += trade_iter.value;
|
|
|
- } else {
|
|
|
- flow_out_value += trade_iter.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
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
-
|
|
|
pub fn check_ready(&mut self) {
|
|
|
if self.is_ready {
|
|
|
return;
|
|
|
@@ -437,8 +523,6 @@ impl AvellanedaStoikov {
|
|
|
async fn processor(&mut self) {
|
|
|
self.update_t_diff();
|
|
|
// info!(?self.t_diff);
|
|
|
- self.update_flow_ratio();
|
|
|
- // info!(?self.flow_ratio_long);
|
|
|
self.update_sigma_square();
|
|
|
// info!(?self.sigma_square);
|
|
|
self.update_gamma();
|
|
|
@@ -472,11 +556,11 @@ impl AvellanedaStoikov {
|
|
|
optimal_bid_price: self.optimal_bid_price,
|
|
|
|
|
|
inventory: self.inventory,
|
|
|
- sigma_square: self.flow_ratio_long,
|
|
|
- gamma: self.flow_ratio_short,
|
|
|
- kappa: self.t_diff,
|
|
|
+ sigma_square: self.open_interest,
|
|
|
+ gamma: self.money_flow_diff,
|
|
|
+ kappa: self.total_cross_diff,
|
|
|
|
|
|
- flow_ratio: self.flow_ratio_long,
|
|
|
+ flow_ratio: self.money_flow,
|
|
|
ref_price: self.ref_price,
|
|
|
});
|
|
|
}
|