|
|
@@ -5,20 +5,68 @@ use standard::{Depth, Ticker, Trade};
|
|
|
|
|
|
const MAX_DATA_LENGTH: usize = 1000;
|
|
|
|
|
|
+// 定制的队列,可以统一指定长度
|
|
|
+#[derive(Debug)]
|
|
|
+pub struct FixedLengthDeque<T> {
|
|
|
+ pub deque: VecDeque<T>,
|
|
|
+ max_len: usize,
|
|
|
+}
|
|
|
+
|
|
|
+impl<T> FixedLengthDeque<T> {
|
|
|
+ fn new(max_len: usize) -> Self {
|
|
|
+ FixedLengthDeque {
|
|
|
+ deque: VecDeque::new(),
|
|
|
+ max_len,
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn push_back(&mut self, value: T) {
|
|
|
+ self.deque.push_back(value);
|
|
|
+ // =================== 之后如果要以时间作为限制,在这里改就行了 ==================
|
|
|
+ // 检查长度,如果超过最大长度,则移除前端元素
|
|
|
+ if self.deque.len() > self.max_len {
|
|
|
+ self.deque.pop_front();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn len(&self) -> usize {
|
|
|
+ self.deque.len()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn get(&self) -> &VecDeque<T> {
|
|
|
+ &self.deque
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
#[derive(Debug)]
|
|
|
pub struct AvellanedaStoikov {
|
|
|
- pub depth_vec: VecDeque<Depth>, // 深度队列
|
|
|
- pub trade_vec: VecDeque<Trade>, // 交易队列
|
|
|
- pub spread_vec: VecDeque<Decimal>, // 市场冲击队列
|
|
|
-
|
|
|
- pub mid_price: Decimal,
|
|
|
- pub ask_price: Decimal,
|
|
|
- pub bid_price: Decimal,
|
|
|
- pub spread: Decimal,
|
|
|
- pub spread_max: Decimal,
|
|
|
- pub spread_min: Decimal,
|
|
|
- pub optimal_ask_price: Decimal,
|
|
|
- pub optimal_bid_price: Decimal,
|
|
|
+ pub depth_vec: FixedLengthDeque<Depth>, // 深度队列
|
|
|
+ pub trade_vec: FixedLengthDeque<Trade>, // 交易队列
|
|
|
+
|
|
|
+ pub mid_price_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub ask_price_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub bid_price_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub spread_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub spread_max_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub spread_min_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub optimal_ask_price_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub optimal_bid_price_vec: FixedLengthDeque<Decimal>,
|
|
|
+
|
|
|
+ pub mid_price: Decimal, // 中间价
|
|
|
+ pub ask_price: Decimal, // 卖一价
|
|
|
+ pub bid_price: Decimal, // 买一价
|
|
|
+ pub spread: Decimal, // 市场冲击
|
|
|
+ pub spread_max: Decimal, // 最大市场冲击
|
|
|
+ pub spread_min: Decimal, // 最小市场冲击
|
|
|
+ pub optimal_ask_price: Decimal, // 卖出价挂单
|
|
|
+ pub optimal_bid_price: Decimal, // 买入价挂单
|
|
|
+
|
|
|
+ pub inventory_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub gamma_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub sigma_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub delta_plus_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub kappa_vec: FixedLengthDeque<Decimal>,
|
|
|
+ pub ref_price_vec: FixedLengthDeque<Decimal>,
|
|
|
|
|
|
pub inventory: Decimal, // 库存,也就是q
|
|
|
pub gamma: Decimal, // γ,库存风险厌恶参数
|
|
|
@@ -36,10 +84,18 @@ impl AvellanedaStoikov {
|
|
|
pub fn new() -> Self {
|
|
|
let avellaneda_stoikov = Self {
|
|
|
// 分别给与MAX_DATA_LENGTH的长度
|
|
|
- depth_vec: VecDeque::with_capacity(MAX_DATA_LENGTH),
|
|
|
- trade_vec: VecDeque::with_capacity(MAX_DATA_LENGTH),
|
|
|
- spread_vec: VecDeque::with_capacity(MAX_DATA_LENGTH),
|
|
|
-
|
|
|
+ depth_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ trade_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+
|
|
|
+ mid_price_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ ask_price_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ bid_price_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ spread_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ spread_max_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ spread_min_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ optimal_ask_price_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ optimal_bid_price_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+
|
|
|
mid_price: Default::default(),
|
|
|
ask_price: Default::default(),
|
|
|
bid_price: Default::default(),
|
|
|
@@ -49,6 +105,13 @@ impl AvellanedaStoikov {
|
|
|
optimal_ask_price: Default::default(),
|
|
|
optimal_bid_price: Default::default(),
|
|
|
|
|
|
+ inventory_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ gamma_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ sigma_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ delta_plus_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ kappa_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+ ref_price_vec: FixedLengthDeque::new(MAX_DATA_LENGTH),
|
|
|
+
|
|
|
inventory: Default::default(),
|
|
|
gamma: Default::default(),
|
|
|
sigma: Default::default(),
|
|
|
@@ -62,72 +125,72 @@ impl AvellanedaStoikov {
|
|
|
|
|
|
// 更新最大市场冲击
|
|
|
pub fn update_spread_max(&mut self) {
|
|
|
- self.spread_max = if let Some(&max_value) = self.spread_vec.iter().max() {
|
|
|
+ self.spread_max = if let Some(&max_value) = self.spread_vec.deque.iter().max() {
|
|
|
max_value
|
|
|
} else {
|
|
|
Decimal::NEGATIVE_ONE
|
|
|
- }
|
|
|
+ };
|
|
|
+ self.spread_max_vec.push_back(self.spread_max);
|
|
|
}
|
|
|
|
|
|
// 更新最小市场冲击
|
|
|
pub fn update_spread_min(&mut self) {
|
|
|
- self.spread_min = if let Some(&min_value) = self.spread_vec.iter().min() {
|
|
|
+ self.spread_min = if let Some(&min_value) = self.spread_vec.deque.iter().min() {
|
|
|
min_value
|
|
|
} else {
|
|
|
Decimal::NEGATIVE_ONE
|
|
|
- }
|
|
|
+ };
|
|
|
+ self.spread_min_vec.push_back(self.spread_min);
|
|
|
}
|
|
|
|
|
|
pub fn update_spread(&mut self, mid_price_now: &Decimal) {
|
|
|
if self.mid_price > Decimal::ZERO {
|
|
|
// 使用mid_price来确认市场冲击
|
|
|
self.spread = (mid_price_now - self.mid_price).abs();
|
|
|
- self.update_spread_max();
|
|
|
- self.update_spread_min();
|
|
|
self.spread_vec.push_back(self.spread);
|
|
|
|
|
|
- // 简易的长度控制
|
|
|
- if self.spread_vec.len() > MAX_DATA_LENGTH {
|
|
|
- self.spread_vec.pop_front();
|
|
|
- }
|
|
|
+ self.update_spread_max();
|
|
|
+ self.update_spread_min();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pub fn update_ref_price(&mut self) {
|
|
|
self.ref_price = self.mid_price;
|
|
|
+ self.ref_price_vec.push_back(self.ref_price);
|
|
|
}
|
|
|
|
|
|
pub fn on_depth(&mut self, depth: &Depth) {
|
|
|
self.depth_vec.push_back(depth.clone());
|
|
|
- self.processor();
|
|
|
|
|
|
- let mid_price_now = (depth.asks[0].price + depth.bids[0].price) / Decimal::TWO;
|
|
|
- self.update_spread(&mid_price_now);
|
|
|
- self.mid_price = mid_price_now;
|
|
|
+ self.ask_price = depth.asks[0].price;
|
|
|
+ self.ask_price_vec.push_back(self.ask_price);
|
|
|
|
|
|
- self.update_ref_price();
|
|
|
+ self.bid_price = depth.bids[0].price;
|
|
|
+ self.bid_price_vec.push_back(self.bid_price);
|
|
|
|
|
|
- info!(?self.mid_price, ?self.spread, ?self.spread_max, ?self.spread_min, ?self.inventory);
|
|
|
+ let mid_price_now = (self.ask_price + self.bid_price) / Decimal::TWO;
|
|
|
+ self.update_spread(&mid_price_now);
|
|
|
+ self.mid_price = mid_price_now;
|
|
|
+ self.mid_price_vec.push_back(self.mid_price);
|
|
|
|
|
|
- // 简易的长度控制
|
|
|
- if self.depth_vec.len() > MAX_DATA_LENGTH {
|
|
|
- self.depth_vec.pop_front();
|
|
|
- }
|
|
|
+ self.processor();
|
|
|
}
|
|
|
|
|
|
pub fn on_trade(&mut self, trade: &Trade) {
|
|
|
self.trade_vec.push_back(trade.clone());
|
|
|
self.processor();
|
|
|
+ }
|
|
|
|
|
|
- // 简易的长度控制
|
|
|
- if self.trade_vec.len() > MAX_DATA_LENGTH {
|
|
|
- self.trade_vec.pop_front();
|
|
|
- }
|
|
|
+ pub fn update_inventory(&mut self, inventory: Decimal) {
|
|
|
+ self.inventory = inventory;
|
|
|
+ self.inventory_vec.push_back(inventory)
|
|
|
}
|
|
|
|
|
|
// #[instrument(skip(self), level="TRACE")]
|
|
|
fn processor(&mut self) {
|
|
|
+ self.update_ref_price();
|
|
|
|
|
|
+ info!("{}, {}", self.mid_price, self.spread_max);
|
|
|
}
|
|
|
|
|
|
// #[instrument(skip(self, ref_ticker_map), level="TRACE")]
|