| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- use std::collections::BTreeMap;
- use rust_decimal::prelude::*;
- use rust_decimal_macros::dec;
- use tracing::{instrument};
- use standard::Ticker;
- use global::public_params;
- #[derive(Debug)]
- pub struct Predictor {
- pub loop_count: i64, // 统计当前预测器更新的次数,loop
- pub market_info_list: Vec<Vec<Decimal>>, // TODO 这里存放的是一个市场数据汇总,后面有时间再优化,arr
- pub mid_price_list: Vec<Decimal>, // 中间价的数组,trade_mp_series
- pub ref_mid_price_per_exchange_per_frame: Vec<Vec<Decimal>>, // 参考交易所的中间价的数组(注意是二维的,因为参考交易所有多个),ref_mp_series
- pub ref_exchange_length: usize, // 参考交易所数量,ref_num
- pub data_length_max: usize, // 各类数据极限长度,防止爆内存,window
- pub alpha: Vec<Decimal>, // 价格系数
- pub gamma: Decimal, // 定价系数
- pub avg_spread_list: Vec<Decimal>, // 平均价差
- }
- /*
- 使用Builder设计模式创建价格预测器,可以有效提高代码整洁度
- 下面的单元测试有使用示例
- */
- impl Predictor {
- pub fn new(ref_exchange_length: usize) -> Self {
- Self {
- loop_count: 0,
- market_info_list: vec![],
- mid_price_list: vec![],
- ref_mid_price_per_exchange_per_frame: vec![],
- ref_exchange_length,
- data_length_max: 10,
- alpha: vec![Decimal::new(1, 0); 100],
- gamma: Decimal::from_f64(0.999).unwrap(),
- avg_spread_list: vec![dec!(0); ref_exchange_length],
- }
- }
- pub fn alpha(mut self, alpha: Vec<Decimal>) -> Self {
- self.alpha = alpha;
- self
- }
- pub fn gamma(mut self, gamma: Decimal) -> Self {
- self.gamma = gamma;
- self
- }
- // 计算任务,python里写作processer,是个错误的单词
- #[instrument(skip(self), level="TRACE")]
- fn processor(&mut self) {
- let last_market_info = self.market_info_list.last().unwrap();
- // 更新mid_price
- let bid_price = last_market_info[public_params::BID_PRICE_INDEX];
- let ask_price = last_market_info[public_params::ASK_PRICE_INDEX];
- let mid_price = (bid_price + ask_price) * dec!(0.5);
- self.mid_price_list.push(mid_price);
- // 更新参考ref_mid_price
- let mut ref_mid_price_per_exchange = vec![];
- for ref_index in 0..self.ref_exchange_length {
- let ref_bid_price = last_market_info[public_params::LENGTH*(1+ref_index)+public_params::BID_PRICE_INDEX];
- let ref_ask_price = last_market_info[public_params::LENGTH*(1+ref_index)+public_params::ASK_PRICE_INDEX];
- let ref_mid_price = (ref_bid_price + ref_ask_price) * dec!(0.5);
- // 依照交易所次序添加到ref_mid_price_per_exchange中
- ref_mid_price_per_exchange.push(ref_mid_price);
- }
- self.ref_mid_price_per_exchange_per_frame.push(ref_mid_price_per_exchange);
- // 价差更新
- (*self).update_avg_spread()
- }
- // 更新平均价差,_update_avg_spread
- #[instrument(skip(self), level="TRACE")]
- fn update_avg_spread(&mut self) {
- let last_ref_mid_price_per_exchange = self.ref_mid_price_per_exchange_per_frame.last().unwrap();
- let mid_price_last = self.mid_price_list.last().unwrap();
- for ref_index in 0..self.ref_exchange_length {
- let bias = last_ref_mid_price_per_exchange[ref_index] * self.alpha[ref_index] - mid_price_last;
- let mut gamma = self.gamma;
- // 如果程序刚刚启动,gamma值不能太大
- if self.loop_count < 100 {
- gamma = dec!(0.9);
- }
- // 检测是否初始化
- if dec!(0).eq(&self.avg_spread_list[ref_index]) {
- self.avg_spread_list[ref_index] = bias;
- } else {
- self.avg_spread_list[ref_index] = self.avg_spread_list[ref_index] * gamma + bias*(dec!(1)-gamma);
- }
- }
- }
- // 长度限定
- #[instrument(skip(self), level="TRACE")]
- fn check_length(&mut self) {
- // 市场汇总信息长度限定
- if self.market_info_list.len() > self.data_length_max {
- self.market_info_list.remove(0);
- }
- // 交易交易所的mid_price长度限定
- if self.mid_price_list.len() > self.data_length_max {
- self.mid_price_list.remove(0);
- }
- // 参考交易所的长度限定
- if self.ref_mid_price_per_exchange_per_frame.len() > self.data_length_max {
- self.ref_mid_price_per_exchange_per_frame.remove(0);
- }
- }
- // 市场信息处理器,也是python里的onTime方法
- #[instrument(skip(self, new_market_info), level="TRACE")]
- pub fn market_info_handler(&mut self, new_market_info: &Vec<Decimal>) {
- // 空数据不处理
- if new_market_info.len() == 0 {
- return;
- }
- if self.loop_count < i64::MAX {
- self.loop_count += 1;
- }
- self.market_info_list.push(new_market_info.clone());
- (*self).processor();
- (*self).check_length();
- }
- // 获取预定价格, 也就是python的Get_ref函数
- #[instrument(skip(self, ref_ticker_map), level="TRACE")]
- pub fn get_ref_price(&mut self, ref_ticker_map: &BTreeMap<String, Ticker>) -> Vec<Vec<Decimal>> {
- let mut ref_price_list = vec![];
- let ref_exchange_names: Vec<_> = ref_ticker_map.keys().collect();
- for ref_index in 0..ref_exchange_names.len() {
- let ref_exchange = ref_exchange_names[ref_index];
- let ticker = ref_ticker_map.get(ref_exchange).unwrap();
- let bid_price = ticker.buy;
- let ask_price = ticker.sell;
- let ref_bid_price = bid_price * self.alpha[ref_index] - self.avg_spread_list[ref_index];
- let ref_ask_price = ask_price * self.alpha[ref_index] - self.avg_spread_list[ref_index];
- ref_price_list.push(vec![ref_bid_price, ref_ask_price]);
- }
- return ref_price_list;
- }
- }
- #[cfg(test)]
- mod tests {
- use std::collections::BTreeMap;
- use std::io;
- use std::io::Write;
- use rust_decimal_macros::dec;
- use standard::Ticker;
- use crate::predictor::Predictor;
- #[test]
- fn predictor_build_test() {
- let mut stdout = io::stdout();
- let predictor1 = Predictor::new(2)
- .alpha(vec![dec!(0.99); 100])
- .gamma(dec!(0.8));
- writeln!(stdout, "predictor1:").unwrap();
- writeln!(stdout, "{:?}", predictor1).unwrap();
- writeln!(stdout, "").unwrap();
- let predictor2 = Predictor::new(2);
- writeln!(stdout, "predictor2:").unwrap();
- writeln!(stdout, "{:?}", predictor2).unwrap();
- writeln!(stdout, "").unwrap();
- }
- #[test]
- fn market_info_handler_test() {
- let mut predictor = Predictor::new(1);
- let market_info_0 = vec![dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89), dec!(0.79), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79)];
- predictor.market_info_handler(&market_info_0);
- let market_info_1 = vec![dec!(0.98), dec!(0.99), dec!(0.56), dec!(0.49), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89), dec!(0.79), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79)];
- predictor.market_info_handler(&market_info_1);
- }
- #[test]
- fn get_ref_price_test() {
- let mut predictor = Predictor::new(1)
- .alpha(vec![dec!(0.99); 100])
- .gamma(dec!(0.8));
- //
- let mut ref_ticker_map: BTreeMap<String, Ticker> = BTreeMap::new();
- ref_ticker_map.insert("binance".to_string(), Ticker{
- time: 0,
- high: Default::default(),
- low: Default::default(),
- sell: dec!(0.93),
- buy: dec!(0.92),
- last: Default::default(),
- volume: Default::default(),
- });
- println!("before market info: {:?}", predictor.get_ref_price(&ref_ticker_map));
- let mut market_info = vec![];
- market_info = vec![dec!(0.99), dec!(1.0), dec!(0.991), dec!(0.79), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89), dec!(0.79), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79)];
- predictor.market_info_handler(&market_info);
- println!("market info 0: {:?}", predictor.get_ref_price(&ref_ticker_map));
- market_info = vec![dec!(0.98), dec!(0.99), dec!(0.981), dec!(0.49), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89)];
- predictor.market_info_handler(&market_info);
- println!("market info 1: {:?}", predictor.get_ref_price(&ref_ticker_map));
- market_info = vec![dec!(0.93), dec!(1.0), dec!(0.931), dec!(0.79), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89)];
- predictor.market_info_handler(&market_info);
- println!("market info 2: {:?}", predictor.get_ref_price(&ref_ticker_map));
- market_info = vec![dec!(0.98), dec!(0.49), dec!(0.981), dec!(0.49), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89)];
- predictor.market_info_handler(&market_info);
- println!("market info 3: {:?}", predictor.get_ref_price(&ref_ticker_map));
- market_info = vec![dec!(0.99), dec!(1.0), dec!(0.991), dec!(0.69), dec!(0.99), dec!(1.0), dec!(0.89), dec!(0.79), dec!(0.89)];
- predictor.market_info_handler(&market_info);
- println!("market info 4: {:?}", predictor.get_ref_price(&ref_ticker_map));
- market_info = vec![dec!(0.98), dec!(0.969), dec!(0.981), dec!(0.49), dec!(0.99), dec!(1.0), dec!(1.0), dec!(1.0), dec!(0.89)];
- predictor.market_info_handler(&market_info);
- println!("market info 5: {:?}", predictor.get_ref_price(&ref_ticker_map));
- }
- }
|