Procházet zdrojové kódy

波动率计算

行情缓存准备提示,算法优化
JiahengHe před 1 rokem
rodič
revize
d354e98c02

+ 1 - 1
strategy/src/binance_usdt_swap.rs

@@ -84,7 +84,7 @@ async fn on_data(bot_arc_clone: Arc<Mutex<Quant>>, update_flag_u: &mut i64, max_
                 quant._update_ticker(SpecialTicker{
                     sell: ticker.a.clone(),
                     buy: ticker.b.clone(),
-                    mid_price: Default::default(),
+                    mid_price: (ticker.a + ticker.b)/Decimal::TWO,
                 }, data.label.clone());
                 let depth = vec![ticker.b, ticker.B, ticker.a, ticker.A];
                 trace_stack.on_after_format();

+ 8 - 1
strategy/src/instant_volatility_indicator.rs

@@ -3,6 +3,7 @@ use rust_decimal::{Decimal, MathematicalOps};
 use tracing::error;
 use crate::ring_buffer::RingBuffer;
 
+#[derive(Debug)]
 pub struct InstantVolatilityIndicator {
     sampling_buffer: RingBuffer,
     processing_buffer: RingBuffer,
@@ -44,11 +45,17 @@ impl InstantVolatilityIndicator {
 
         sum
     }
+    pub fn get_process(&self) {
+        if self.sampling_buffer.is_full() {
+            return;
+        }
+        self.sampling_buffer.process();
+    }
 
     // 获取波动率,缓存器没满不返回波动率
     pub fn processing_calculation(&self) -> Decimal{
         if self.processing_buffer.is_full() {
-            self.processing_buffer.get_last_value().unwrap()
+            return self.processing_buffer.get_last_value().unwrap();
         }
         Decimal::ZERO
     }

+ 10 - 10
strategy/src/predictor_new.rs

@@ -1,7 +1,7 @@
 
 use rust_decimal::prelude::*;
 use rust_decimal_macros::dec;
-use tracing::{debug};
+use tracing::{debug, info};
 use global::public_params;
 use standard::Ticker;
 use crate::instant_volatility_indicator::InstantVolatilityIndicator;
@@ -104,15 +104,15 @@ impl PredictorNew {
         波动率计算(根据最近成交价,EWMA波动率算法)
     **/
     pub fn update_std(&mut self) {
-        let gamma = self.gamma.to_f64().unwrap();
+        let gamma = self.gamma;
         // 如果程序刚刚启动,gamma值不能太大
         // if self.loop_count < 100 {
         //     gamma = 0.9f64;
         // }
         let len = self.transaction_prices.len();
-        let rtn:f64 = (self.transaction_prices[len - 1].to_f64().unwrap() / self.transaction_prices[len - 2].to_f64().unwrap()).ln();
-        let result: f64 = gamma * rtn.powf(2.0) + (1f64 - gamma) * self.variance.to_f64().unwrap();
-        self.variance = Decimal::from_f64(result.sqrt()).unwrap();
+        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();
     }
 
     /**
@@ -145,8 +145,8 @@ impl PredictorNew {
     }
 
     pub fn calc_kappa(&mut self, gamma: &Decimal, dk: Decimal, deviation_range: Decimal) -> Decimal {
-        let e = std::f64::consts::E.powf(dk.to_f64().unwrap()) - 1f64;
-        gamma / Decimal::from_f64(e).unwrap() / deviation_range
+        let e = Decimal::E.powf(dk.to_f64().unwrap()) - Decimal::ONE;
+        gamma / e / deviation_range
     }
 
     /**
@@ -154,8 +154,8 @@ impl PredictorNew {
     **/
     pub fn calc_theta(&mut self, gamma: Decimal, kappa: Decimal) -> Decimal {
         let a = gamma * self.variance * self.variance;
-        let ln = (Decimal::ONE + gamma / kappa).to_f64().unwrap().ln();
-        let b = Decimal::TWO / gamma * Decimal::from_f64(ln).unwrap();
+        let ln = (Decimal::ONE + gamma / kappa).ln();
+        let b = Decimal::TWO / gamma * ln;
         (a + b) / Decimal::TWO
     }
 
@@ -246,7 +246,7 @@ impl PredictorNew {
         let mut ref_price_list = Vec::new();
         let std = self.vol.processing_calculation();
         if std == Decimal::ZERO {
-            Vec::new()
+            return Vec::new();
         }
         let ira = Decimal::from_str("5").unwrap();
         let dd = self.calc_deviation_range(ira.clone());

+ 32 - 11
strategy/src/quant.rs

@@ -21,6 +21,7 @@ use global::trace_stack::TraceStack;
 use standard::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, SpecialTicker, Ticker};
 use standard::exchange::{Exchange};
 use standard::exchange::ExchangeEnum::{BinanceSpot, BinanceSwap, BitgetSpot, GateSpot, GateSwap, KucoinSwap};
+use crate::instant_volatility_indicator::InstantVolatilityIndicator;
 
 use crate::model::{LocalPosition, OrderInfo, TokenParam, TraderMsg};
 use crate::predictor::Predictor;
@@ -164,7 +165,25 @@ impl Quant {
             ref_name: Default::default(),
             trade_name: "".to_string(),
             ready: 0,
-            predictor: Default::default(),
+            predictor: PredictorNew{
+                loop_count: 0,
+                market_info_list: vec![],
+                mid_price_list: vec![],
+                ref_mid_price_per_exchange_per_frame: vec![],
+                ref_exchange_length: 0,
+                data_length_max: 0,
+                alpha: vec![],
+                gamma: Default::default(),
+                avg_spread_list: vec![],
+                transaction_prices: vec![],
+                variance: Default::default(),
+                balance_value: Default::default(),
+                max_spread: Default::default(),
+                min_spread: Default::default(),
+                rl_num: Default::default(),
+                max_position_value: Default::default(),
+                vol: InstantVolatilityIndicator::new(1, 1),
+            },
             market: Market {
                 symbol: symbol.clone(),
                 base_asset: "".to_string(),
@@ -683,7 +702,9 @@ impl Quant {
         // }
         // 只用第一参考交易所最佳买卖价的中间价
         if name == self.ref_name[0] {
-            self.predictor.market_update(data.mid_price);
+            self.predictor.market_update(data.mid_price.clone());
+            // 查看进度
+            self.predictor.vol.get_process();
         }
         self.tickers.insert(name, data);
 
@@ -1021,15 +1042,15 @@ impl Quant {
                 self.stop().await;
             }
         }
-
-        // 定价异常风控
-        if self.ready == 1 && (self.strategy.ref_price - self.strategy.mp).abs() / self.strategy.mp > dec!(0.03) {
-
-            let exit_msg = format!("{} 定价偏离过大,怀疑定价异常,退出。", self.params.account_name);
-            warn!(exit_msg);
-            warn!(?self.strategy.ref_price, ?self.strategy.mp);
-            self.exit_msg = exit_msg;
-            self.stop().await;
+        if self.strategy.ref_price != Decimal::ZERO {
+            // 定价异常风控
+            if self.ready == 1 && (self.strategy.ref_price - self.strategy.mp).abs() / self.strategy.mp > dec!(0.03) {
+                let exit_msg = format!("{} 定价偏离过大,怀疑定价异常,退出。", self.params.account_name);
+                warn!(exit_msg);
+                warn!(?self.strategy.ref_price, ?self.strategy.mp);
+                self.exit_msg = exit_msg;
+                self.stop().await;
+            }
         }
     }
 

+ 29 - 4
strategy/src/ring_buffer.rs

@@ -1,22 +1,22 @@
 use std::collections::VecDeque;
 use rust_decimal::{Decimal, MathematicalOps};
 use rust_decimal::prelude::{FromPrimitive};
+use tracing::info;
 
 /**
     环形缓存器
 **/
+#[derive(Debug)]
 pub struct RingBuffer {
     buffer: VecDeque<Decimal>,
-    length: usize,
-    delimiter: usize
+    length: usize
 }
 
 impl RingBuffer {
     pub fn new(length: usize) -> Self {
         RingBuffer {
             buffer: VecDeque::with_capacity(length),
-            length,
-            delimiter: 0usize
+            length
         }
     }
 
@@ -25,6 +25,10 @@ impl RingBuffer {
         self.buffer = VecDeque::with_capacity(self.length);
     }
 
+    pub fn process(&self){
+        info!("行情收集进度:{} / {}", self.buffer.len(), self.length);
+    }
+
     // 添加元素
     pub fn add_value(&mut self, val: Decimal) {
         if self.buffer.len() < self.length {
@@ -98,8 +102,22 @@ impl RingBuffer {
 
 #[cfg(test)]
 mod tests {
+    use std::collections::VecDeque;
+    use std::str::FromStr;
     use rust_decimal::{Decimal, MathematicalOps};
 
+    #[test]
+    fn extend_test(){
+        let mut arr: VecDeque<Decimal> = VecDeque::with_capacity(6);
+        let mut extend_arr: VecDeque<Decimal> = VecDeque::with_capacity(6);
+        for i in 0..6 {
+            arr.push_back(Decimal::from(i));
+        }
+        extend_arr.extend(arr.iter().clone());
+        println!("{:?}", arr);
+        println!("{:?}", extend_arr);
+    }
+
     #[test]
     fn len_test() {
         let mut arr: Vec<Decimal> = Vec::from(vec![Decimal::new(1, 0), Decimal::new(2, 0), Decimal::new(3, 0), Decimal::new(4, 0), Decimal::new(5, 0)]);
@@ -113,4 +131,11 @@ mod tests {
         sum = sum.sqrt().unwrap();
         println!("{:?}", sum);
     }
+
+    #[test]
+    fn test_calc(){
+        let dk = Decimal::from_str("0.0000000000000000007549486024").unwrap();
+        let e = Decimal::E.powd(dk);
+        println!("{:?}",e);
+    }
 }

+ 0 - 2
strategy/src/strategy.rs

@@ -1237,8 +1237,6 @@ impl Strategy {
         if self.is_ready {
             return;
         }
-
-        info!("预热中");
     }
 
     // 在满足条件后,返回非空command,否则返回一个空的command。原文的onTime。