|
|
@@ -26,7 +26,10 @@ pub struct AvellanedaStoikov {
|
|
|
pub trade_long_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
pub trade_short_vec: FixedTimeRangeDeque<Trade>, // 交易队列
|
|
|
pub spread_vec: FixedTimeRangeDeque<Decimal>,
|
|
|
+ pub ticker_vec: FixedTimeRangeDeque<Ticker>,
|
|
|
+ pub vwpin_source_vec: FixedTimeRangeDeque<Decimal>, // vpin计算源数据
|
|
|
|
|
|
+ pub volume24h: Decimal, // 最新的24小时成交数量
|
|
|
pub mid_price: Decimal, // 中间价
|
|
|
pub ask_price: Decimal, // 卖一价
|
|
|
pub bid_price: Decimal, // 买一价
|
|
|
@@ -43,6 +46,8 @@ pub struct AvellanedaStoikov {
|
|
|
pub gamma: Decimal, // γ,库存风险厌恶参数
|
|
|
pub kappa: Decimal, // κ 订单簿 流动性 参数
|
|
|
|
|
|
+ pub vwpin: Decimal, // vwpin值
|
|
|
+
|
|
|
pub flow_ratio_long: Decimal, // 资金流比例
|
|
|
pub flow_ratio_short: Decimal, // 资金流比例
|
|
|
|
|
|
@@ -75,7 +80,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),
|
|
|
+ vwpin_source_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
|
|
|
+ volume24h: Default::default(),
|
|
|
|
|
|
mid_price: Default::default(),
|
|
|
ask_price: Default::default(),
|
|
|
@@ -107,6 +115,7 @@ impl AvellanedaStoikov {
|
|
|
flow_ratio_long: Decimal::ONE,
|
|
|
level: Default::default(),
|
|
|
flow_ratio_short: Default::default(),
|
|
|
+ vwpin: Default::default(),
|
|
|
};
|
|
|
|
|
|
avellaneda_stoikov
|
|
|
@@ -165,9 +174,17 @@ impl AvellanedaStoikov {
|
|
|
let bid_size = depth.bids[0].size;
|
|
|
self.mid_price = (self.ask_price * bid_size + self.bid_price * ask_size) / (ask_size + bid_size);
|
|
|
|
|
|
+ let total_size = ask_size + bid_size;
|
|
|
+
|
|
|
+ let vwpin_item = total_size/self.volume24h * (ask_size - bid_size) / total_size;
|
|
|
+
|
|
|
+ self.vwpin_source_vec.push_back(vwpin_item);
|
|
|
+
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
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());
|
|
|
@@ -177,6 +194,13 @@ impl AvellanedaStoikov {
|
|
|
self.processor().await;
|
|
|
}
|
|
|
|
|
|
+ pub async fn on_ticker(&mut self, ticker: &Ticker) {
|
|
|
+ self.ticker_vec.push_back(ticker.clone());
|
|
|
+ self.volume24h = ticker.volume;
|
|
|
+
|
|
|
+ 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));
|
|
|
@@ -404,6 +428,10 @@ impl AvellanedaStoikov {
|
|
|
self.flow_ratio_short = Self::calc_flow_ratio(&self.flow_ratio_short, &dec!(0), &mut self.trade_long_vec);
|
|
|
}
|
|
|
|
|
|
+ pub fn update_vwpin(&mut self) {
|
|
|
+ self.vwpin = self.vwpin_source_vec.deque.iter().copied().sum();
|
|
|
+ }
|
|
|
+
|
|
|
pub fn check_ready(&mut self) {
|
|
|
if self.is_ready {
|
|
|
return;
|
|
|
@@ -483,6 +511,7 @@ impl AvellanedaStoikov {
|
|
|
sigma_square: self.flow_ratio_long,
|
|
|
gamma: self.flow_ratio_short,
|
|
|
kappa: self.t_diff,
|
|
|
+ vwpin: self.vwpin,
|
|
|
|
|
|
flow_ratio: self.flow_ratio_long,
|
|
|
ref_price: self.ref_price,
|