|
|
@@ -1,357 +0,0 @@
|
|
|
-
|
|
|
-use rust_decimal::prelude::*;
|
|
|
-use rust_decimal_macros::dec;
|
|
|
-use global::public_params;
|
|
|
-use crate::instant_volatility_indicator::InstantVolatilityIndicator;
|
|
|
-
|
|
|
-#[derive(Debug)]
|
|
|
-pub struct PredictorNew {
|
|
|
- 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>, // 平均价差
|
|
|
-//
|
|
|
- pub transaction_prices: Vec<Decimal>, // 中间价记录
|
|
|
- pub variance: Decimal, // 波动率
|
|
|
- pub balance_value: Decimal, // 持仓价值
|
|
|
-// 手动输入
|
|
|
- pub max_spread: Decimal, // 最大点差
|
|
|
- pub min_spread: Decimal, // 最小点差
|
|
|
- pub rl_num: Decimal, // 取价坐标
|
|
|
- pub ira: Decimal, // 取值坐标
|
|
|
- pub max_position_value: Decimal, // 最大持仓(u)
|
|
|
-
|
|
|
- pub vol: InstantVolatilityIndicator // 波动率计算类
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- 使用Builder设计模式创建价格预测器,可以有效提高代码整洁度
|
|
|
- 下面的单元测试有使用示例
|
|
|
-*/
|
|
|
-impl PredictorNew {
|
|
|
- pub fn new(ref_exchange_length: usize, max_spread: Decimal, min_spread: Decimal, rl_num: Decimal, max_position_value: Decimal, ira: Decimal) -> 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],
|
|
|
- transaction_prices: Vec::new(),
|
|
|
- max_spread,
|
|
|
- min_spread,
|
|
|
- variance: Decimal::ZERO,
|
|
|
- balance_value: Decimal::ZERO,
|
|
|
- rl_num,
|
|
|
- ira,
|
|
|
- max_position_value,
|
|
|
- vol: InstantVolatilityIndicator::new(30, 15)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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,是个错误的单词
|
|
|
- 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);
|
|
|
- // debug!(?last_market_info);
|
|
|
- // debug!(?bid_price, ?ask_price, ?mid_price);
|
|
|
- self.mid_price_list.push(mid_price.clone());
|
|
|
- self.transaction_prices.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);
|
|
|
- // debug!(?ref_bid_price, ?ref_ask_price, ?ref_mid_price);
|
|
|
- // 依照交易所次序添加到ref_mid_price_per_exchange中
|
|
|
- ref_mid_price_per_exchange.push(ref_mid_price);
|
|
|
- }
|
|
|
- // debug!(?ref_mid_price_per_exchange);
|
|
|
- let first_price = ref_mid_price_per_exchange[0].clone();
|
|
|
- self.ref_mid_price_per_exchange_per_frame.push(ref_mid_price_per_exchange);
|
|
|
-
|
|
|
- self.transaction_prices.push(first_price);
|
|
|
- // 波动率更新
|
|
|
- self.update_std();
|
|
|
- // 价差更新
|
|
|
- // (*self).update_avg_spread()
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 波动率计算(根据最近成交价,EWMA波动率算法)
|
|
|
- **/
|
|
|
- pub fn update_std(&mut self) {
|
|
|
- let gamma = self.gamma;
|
|
|
- // 如果程序刚刚启动,gamma值不能太大
|
|
|
- // if self.loop_count < 100 {
|
|
|
- // gamma = 0.9f64;
|
|
|
- // }
|
|
|
- let len = self.transaction_prices.len();
|
|
|
- if len < 3usize {
|
|
|
- return;
|
|
|
- }
|
|
|
- // info!(?self.transaction_prices);
|
|
|
- let rtn: Decimal = (self.transaction_prices[len - 1] / self.transaction_prices[len - 2]).ln();
|
|
|
- let result: Decimal = gamma * rtn.powi(2) + (Decimal::ONE - gamma) * self.variance;
|
|
|
- self.variance = result.sqrt().unwrap();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 计算gamma值
|
|
|
- **/
|
|
|
- pub fn calc_gamma(&mut self, ira: Decimal, variance: &Decimal) -> Decimal {
|
|
|
- self.max_spread / Decimal::TWO * self.balance_value * variance.powi(2) * ira
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 计算价格偏差范围
|
|
|
- **/
|
|
|
- pub fn calc_deviation_range(&mut self, ira: Decimal) -> Decimal {
|
|
|
- return (self.rl_num - ira) * self.max_spread + ira * self.min_spread;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 计算预定价格
|
|
|
- **/
|
|
|
- pub fn calc_rp(&mut self, gamma: &Decimal, std: &Decimal) -> Decimal{
|
|
|
- let last_market_info = self.market_info_list.last().unwrap();
|
|
|
- let ref_bid_price = last_market_info[public_params::LENGTH+public_params::BID_PRICE_INDEX];
|
|
|
- let ref_ask_price = last_market_info[public_params::LENGTH+public_params::ASK_PRICE_INDEX];
|
|
|
- let ref_mid_price = (ref_bid_price + ref_ask_price) * dec!(0.5);
|
|
|
- ref_mid_price - self.balance_value * gamma * std * std
|
|
|
- }
|
|
|
-
|
|
|
- pub fn calc_dk(&mut self, gamma: &Decimal, std: &Decimal) -> Decimal {
|
|
|
- return ((self.max_spread + self.min_spread)/Decimal::TWO * gamma - std * std * gamma * gamma) / Decimal::TWO;
|
|
|
- }
|
|
|
-
|
|
|
- pub fn calc_kappa(&mut self, gamma: &Decimal, dk: Decimal, deviation_range: Decimal) -> Decimal {
|
|
|
- let e = Decimal::E.powf(dk.to_f64().unwrap()) - Decimal::ONE;
|
|
|
- gamma / e / deviation_range
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- 计算价差
|
|
|
- **/
|
|
|
- pub fn calc_theta(&mut self, gamma: Decimal, kappa: Decimal, std: &Decimal) -> Decimal {
|
|
|
- let a = gamma * std * std;
|
|
|
- let ln = (Decimal::ONE + gamma / kappa).ln();
|
|
|
- let b = Decimal::TWO / gamma * ln;
|
|
|
- (a + b) / Decimal::TWO
|
|
|
- }
|
|
|
-
|
|
|
- // 更新平均价差,_update_avg_spread
|
|
|
- // 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);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // 长度限定
|
|
|
- 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);
|
|
|
- }
|
|
|
- // 成交价纪录
|
|
|
- if self.transaction_prices.len() > 10usize {
|
|
|
- self.transaction_prices.remove(0);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 市场信息处理器,也是python里的onTime方法
|
|
|
- pub fn market_info_handler(&mut self, new_market_info: &Vec<Decimal>) {
|
|
|
- // debug!(?new_market_info);
|
|
|
- // 空数据不处理
|
|
|
- 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();
|
|
|
- }
|
|
|
-
|
|
|
- pub fn market_update(&mut self, best_mid_price: Decimal){
|
|
|
- self.vol.add_sample(best_mid_price);
|
|
|
- }
|
|
|
-
|
|
|
- // 获取预定价格, 也就是python的Get_ref函数
|
|
|
- // 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 mid_price = (bid_price + ask_price) / Decimal::TWO;
|
|
|
- // let ref_bid_price = mid_price * self.alpha[ref_index] - self.avg_spread_list[ref_index];
|
|
|
- // let ref_ask_price = mid_price * self.alpha[ref_index] + self.avg_spread_list[ref_index];
|
|
|
- //
|
|
|
- // ref_price_list.push(vec![ref_bid_price, ref_ask_price]);
|
|
|
- // }
|
|
|
- // debug!(?ref_price_list);
|
|
|
- //
|
|
|
- // return ref_price_list;
|
|
|
- // }
|
|
|
- pub fn get_ref_price(&mut self) -> Vec<Vec<Decimal>>{
|
|
|
- let mut ref_price_list = Vec::new();
|
|
|
- // let std = self.vol.processing_calculation();
|
|
|
- let std = self.variance;
|
|
|
- if std == Decimal::ZERO {
|
|
|
- return Vec::new();
|
|
|
- }
|
|
|
- let ira = self.ira;
|
|
|
- let dd = self.calc_deviation_range(ira.clone());
|
|
|
- let gamma = self.calc_gamma(ira.clone(), &std);
|
|
|
- let rp = self.calc_rp(&gamma, &std);
|
|
|
- let dk = self.calc_dk(&gamma, &std);
|
|
|
- let kappa = self.calc_kappa(&gamma, dk, dd);
|
|
|
- let theta = self.calc_theta(gamma, kappa, &std);
|
|
|
- ref_price_list.push(vec![rp + theta , rp - theta]);
|
|
|
- // info!(?std, ?dd, ?gamma, ?rp, ?dk, ?kappa, ?theta, ?ref_price_list);
|
|
|
-
|
|
|
- // let std2 = self.variance;
|
|
|
- // let dd2 = self.calc_deviation_range(ira.clone());
|
|
|
- // let gamma2 = self.calc_gamma(ira, &std2);
|
|
|
- // let rp2 = self.calc_rp(&gamma, &std2);
|
|
|
- // let dk2 = self.calc_dk(&gamma, &std2);
|
|
|
- // let kappa2 = self.calc_kappa(&gamma, dk, dd);
|
|
|
- // let theta2 = self.calc_theta(gamma, kappa, &std2);
|
|
|
- // let x = vec![rp2 + theta2 , rp2 - theta2];
|
|
|
- // info!(?std2, ?dd2, ?gamma2, ?rp2, ?dk2, ?kappa2, ?theta2, ?x);
|
|
|
- ref_price_list
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#[cfg(test)]
|
|
|
-mod tests {
|
|
|
- use std::collections::BTreeMap;
|
|
|
- use std::io;
|
|
|
- use std::io::Write;
|
|
|
- use std::str::FromStr;
|
|
|
- use rust_decimal::Decimal;
|
|
|
- use rust_decimal_macros::dec;
|
|
|
- use standard::Ticker;
|
|
|
- use crate::predictor_new::PredictorNew;
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn predictor_build_test() {
|
|
|
- let mut stdout = io::stdout();
|
|
|
-
|
|
|
- let predictor1 = PredictorNew::new(2, Default::default(), Default::default(), Default::default(), Default::default(), Decimal::ONE)
|
|
|
- .alpha(vec![dec!(0.99); 100])
|
|
|
- .gamma(dec!(0.8));
|
|
|
- writeln!(stdout, "predictor1:").unwrap();
|
|
|
- writeln!(stdout, "{:?}", predictor1).unwrap();
|
|
|
- writeln!(stdout, "").unwrap();
|
|
|
-
|
|
|
- let predictor2 = PredictorNew::new(2, Default::default(), Default::default(), Default::default(), Default::default(), Decimal::ONE);
|
|
|
- writeln!(stdout, "predictor2:").unwrap();
|
|
|
- writeln!(stdout, "{:?}", predictor2).unwrap();
|
|
|
- writeln!(stdout, "").unwrap();
|
|
|
- }
|
|
|
-
|
|
|
- #[test]
|
|
|
- fn market_info_handler_test() {
|
|
|
- let mut predictor = PredictorNew::new(1, Default::default(), Default::default(), Default::default(), Default::default(), Decimal::ONE);
|
|
|
- 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 = PredictorNew::new(1, Default::default(), Default::default(), Default::default(), Default::default(), Decimal::ONE)
|
|
|
- .alpha(vec![dec!(0.99); 100])
|
|
|
- .gamma(dec!(0.8));
|
|
|
- predictor.balance_value = Decimal::from_str("0.5").unwrap();
|
|
|
- predictor.max_spread = Decimal::from_str("0.5").unwrap();
|
|
|
- predictor.min_spread = Decimal::from_str("0.01").unwrap();
|
|
|
- //
|
|
|
- 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());
|
|
|
-
|
|
|
- let mut 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());
|
|
|
- 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());
|
|
|
- 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());
|
|
|
- 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());
|
|
|
- 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());
|
|
|
- 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());
|
|
|
- }
|
|
|
-}
|