JiahengHe 1 жил өмнө
parent
commit
ded53c13be

+ 2 - 1
strategy/Cargo.toml

@@ -18,4 +18,5 @@ tracing = "0.1"
 tracing-subscriber = "0.3.17"
 standard = { path = "../standard" }
 global = { path = "../global" }
-exchanges = { path = "../exchanges" }
+exchanges = { path = "../exchanges" }
+ndarray = "0.15.6"

+ 2 - 1
strategy/src/lib.rs

@@ -13,4 +13,5 @@ mod kucoin_spot;
 mod bitget_spot;
 mod predictor_new;
 mod instant_volatility_indicator;
-mod ring_buffer;
+mod ring_buffer;
+mod memoized_func;

+ 37 - 0
strategy/src/memoized_func.rs

@@ -0,0 +1,37 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+use rust_decimal::Decimal;
+
+type Func = Rc<dyn Fn(Decimal, Decimal) -> Vec<Decimal>>;
+
+pub struct MemoizedFunc {
+    func: Func,
+    last_a: Decimal,
+    last_b: Decimal,
+    last_val: Vec<Decimal>
+}
+
+impl MemoizedFunc {
+    pub(crate) fn new(func: Func) -> Self {
+        MemoizedFunc {
+            func,
+            last_a: Decimal::ZERO,
+            last_b: Decimal::ZERO,
+            last_val: Vec::new()
+        }
+    }
+
+    pub fn call(&mut self, a: Decimal, b: Decimal) -> Vec<Decimal> {
+        if self.last_a == a  && self.last_b == b{
+            return self.last_val.clone();
+        }
+
+        let val = (self.func)(a.clone(), b.clone());
+
+        self.last_a = a;
+        self.last_b = b;
+        self.last_val = val.clone();
+
+        val
+    }
+}

+ 3 - 1
strategy/src/predictor_new.rs

@@ -2,6 +2,7 @@
 use rust_decimal::prelude::*;
 use rust_decimal_macros::dec;
 use tracing::{debug, info};
+use tracing::field::debug;
 use global::public_params;
 use standard::Ticker;
 use crate::instant_volatility_indicator::InstantVolatilityIndicator;
@@ -244,7 +245,7 @@ impl PredictorNew {
     // }
     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();
         }
@@ -256,6 +257,7 @@ impl PredictorNew {
         let kappa = self.calc_kappa(&gamma, dk, dd);
         let theta = self.calc_theta(gamma, kappa);
         ref_price_list.push(vec![rp + theta , rp - theta]);
+        debug!(?ref_price_list);
         ref_price_list
     }
 }

+ 3 - 1
strategy/src/strategy.rs

@@ -511,7 +511,7 @@ impl Strategy {
             error!("未知做市类型:mode={}", mode);
             panic!("未知做市类型:mode={}", mode);
         }
-        debug!(?mode, ?buy_start, ?sell_start, ?mp);
+        info!(?mode, ?buy_start, ?sell_start, ?mp);
 
         // 开仓相关
         avoid = min(dec!(0.001), open * dec!(0.05));
@@ -543,6 +543,8 @@ impl Strategy {
         }
         self.open_dist = open_dist.clone();
         self.close_dist = close_dist.clone();
+        info!(?open_dist);
+        info!(?close_dist);
         debug!(?open_dist);
         debug!(?close_dist);
     }

+ 251 - 4
strategy/src/utils.rs

@@ -1,9 +1,19 @@
+use std::collections::HashMap;
+use std::iter::Map;
 use std::ops::{Div, Mul};
+use std::rc::Rc;
+use std::str::FromStr;
+use std::sync::Arc;
+use chrono::Month::December;
 use chrono::Utc;
 use rand::Rng;
-use rust_decimal::Decimal;
+use rust_decimal::{Decimal, MathematicalOps};
 use tracing::error;
 use global::public_params;
+use ndarray::Array1;
+use rust_decimal::prelude::FromPrimitive;
+use tokio::fs::DirEntry;
+use crate::memoized_func::MemoizedFunc;
 
 // 生成订单的id,可以根据交易所名字来
 pub fn generate_client_id(exchange_name_some: Option<String>) -> String {
@@ -108,11 +118,246 @@ pub fn equidistant_sequence(start: i32, end: i32, step: i32) -> Vec<i32> {
     series
 }
 
+// params = curve_fit(lambda t, a, b: a*np.exp(-b*t),
+//                                price_levels,
+//                                lambdas_adj,
+//                                p0=(self._alpha, self._kappa),
+//                                method='dogbox',
+//                                bounds=([0, 0], [np.inf, np.inf]))
+pub fn curve_fit(f: Rc<dyn Fn(&Vec<Decimal>, Decimal, Decimal) -> Vec<Decimal>>, x_data: Vec<Decimal>, y_data: Vec<Decimal>,
+                                                              p0: (Decimal, Decimal), method: String, bounds: (Vec<Decimal>, Vec<Decimal>)) {
+    let p0_arr = vec![p0.0, p0.1];
+    let n = p0_arr.len();
+    let lb = bounds.0;
+    let ub = bounds.1;
+    let bounded_problem = lb.iter().any(|&x| x > -Decimal::MIN) | ub.iter().any(|&y| y < Decimal::MAX);
+
+    if method.eq("lm") && bounded_problem {
+        // 主动抛出异常
+    }
+    let func: MemoizedFunc = MemoizedFunc::new(wrap_func(f, x_data, y_data));
+    let jac: &str = "2-point";
+}
+
+fn wrap_func(func: Rc<dyn Fn(&Vec<Decimal>, Decimal, Decimal) -> Vec<Decimal>>,
+              xdata: Vec<Decimal>,
+              ydata: Vec<Decimal>)
+              -> Rc<dyn Fn(Decimal, Decimal) -> Vec<Decimal>> {
+    let y_data = ydata.clone();
+    Rc::new(move |a, b| {
+        let m_data = func(&xdata, a, b);
+        m_data.iter().zip(y_data.iter()).map(|(&x_data, &y_item)| x_data - y_item).collect()
+    })
+}
+
+
+
+fn least_squares(mut fun: MemoizedFunc, x0: Vec<Decimal>){
+    let jac: &str = "2-point";
+    let bounds = (vec![Decimal::ZERO, Decimal::ZERO], vec![Decimal::MAX, Decimal::MAX]);
+    let method = "dogbox";
+    let kwargs: HashMap<&str, &str> = HashMap::new();
+    let lb = bounds.0;
+    let ub = bounds.1;
+    let x_scale: Vec<Decimal> = vec![Decimal::ONE];
+    let loos: &str = "linear";
+    let f_scale: Decimal = Decimal::ONE;
+
+    let f0 = fun.call(x0[0], x0[1]);
+    let f0_1 = f0.clone();
+    let n = x0.len();
+    let m = f0.len();
+    let dot: Decimal = f0.iter().zip(f0_1.iter()).map(|(x, y)| x * y).sum();
+    let initial_cost = Decimal::ONE/ Decimal::TWO * dot;
+
+    let j0 = approx_derivative(&mut fun, x0, f0);
+    let tr_solver = "exact";
+    let tr_options = {};
+    let verbose = 0;
+    let ftol = Decimal::ONE.powi(-8);
+    let xtol = Decimal::ONE.powi(-8);
+    let gtol = Decimal::ONE.powi(-8);
+    let max_nfev = {};
+    let loss_function = "NONE";
+    let jac_wrapped = jac_wrapped(&mut fun);
+
+
+
+}
+
+fn dogbox<F: Fn(Vec<Decimal>, Vec<Decimal>) -> Vec<Vec<Decimal>>>(fun: Rc<dyn Fn(&Vec<Decimal>, Decimal, Decimal) -> Vec<Decimal>>,
+                                                                  jac_wrapped: F, x0: Vec<Decimal>, f0: Vec<Decimal>, j0: Vec<Vec<Decimal>>,
+                                                                  lb: Vec<Decimal>, ub: Vec<Decimal>, ftol: Decimal, xtol: Decimal, gtol: Decimal,
+                                                                  x_scale: Vec<Decimal>, tr_solver: &str, verbose: i32) {
+    let f = f0.clone();
+    let f_true = f.clone();
+    let nfev = 1;
+    let J = j0.clone();
+    let njev = 1;
+    // 0.5 * np.dot(f, f)
+    let cost = Decimal::ONE / Decimal::TWO * f.iter().zip(&f).map(|(a, b)| a * b).sum();
+    let J_T = transpose(&j0);
+    let g = (0..J_T[0].len()).map(|i| {
+        J_T.iter().zip(&f).map(|(row, &f_value)| row[i] * f_value).sum()
+    }).collect();
+    let scale = x_scale.clone();
+    let scale_inv = Decimal::ONE / x_scale;
+
+
+
+
+}
+
+fn jac_wrapped(fun: &mut MemoizedFunc) -> impl Fn(Vec<Decimal>, Vec<Decimal>) -> Vec<Vec<Decimal>> {
+    |x, f| {
+        approx_derivative(fun, x, f)
+    }
+}
+
+
+
+fn approx_derivative(fun: &mut MemoizedFunc, x0: Vec<Decimal>, f0: Vec<Decimal>) -> Vec<Vec<Decimal>>{
+    // let rel_step: Vec<Decimal> = Vec::new();
+    // let method = "2-point";
+    let bounds = (vec![Decimal::ZERO, Decimal::ZERO], vec![Decimal::MAX, Decimal::MAX]);
+    let lb = bounds.0;
+    let ub = bounds.1;
+    let mut h = compute_absolute_step(x0.clone());
+    let h_use_one_sided = adjust_scheme_to_bounds(x0.clone(), h, lb, ub);
+    h = h_use_one_sided.0;
+    // let use_one_sided = h_use_one_sided.1;
+    return dense_difference(fun, x0, f0, h);
+}
+
+fn dense_difference(fun: &mut MemoizedFunc, x0: Vec<Decimal>, f0: Vec<Decimal>, h: Vec<Decimal>) -> Vec<Vec<Decimal>>{
+    let method = "2-point";
+    let m = f0.len();
+    let n = x0.len();
+    let h_len = h.len();
+    let mut j_transposed = vec![vec![Decimal::ZERO; n]; m];
+    let mut h_vecs = vec![vec![Decimal::ZERO; h_len]; h_len];
+
+    for i in 0..h_len {
+        h_vecs[i][i] = h[i];
+    }
+
+    for i in 0..h_len {
+        let x0_clone = x0.clone();
+        let x :Vec<Decimal> = x0_clone.iter().zip(h_vecs[i].iter()).map(|(&x0_val, &h_vec_val)| x0_val + h_vec_val).collect();
+        let dx: Decimal = x[i] - x0_clone[i];
+        let df = fun.call(x[0], x[1]);
+        j_transposed[i] = df.iter().map(|&df_val| df_val/dx).collect();
+    }
+    // if m == 1usize {
+    //     let result = j_transposed.into_iter().flatten().collect();
+    //     return result;
+    // } else if m == 2usize {
+    //
+    // } else{
+    //
+    // }
+    let transposed = transpose(&j_transposed);
+    return transposed
+}
+
+// 二维数组的转置操作
+fn transpose<T: Clone>(v: &Vec<Vec<T>>) -> Vec<Vec<T>> {
+    let mut result = vec![vec![v[0][0].clone(); v.len()]; v[0].len()];
+    for (i, row) in v.iter().enumerate() {
+        for (j, value) in row.iter().enumerate() {
+            result[j][i] = value.clone();
+        }
+    }
+    result
+}
+
+fn adjust_scheme_to_bounds(x0: Vec<Decimal>, h: Vec<Decimal>, lb: Vec<Decimal>, ub: Vec<Decimal>) -> (Vec<Decimal>, Vec<bool>){
+    let num_steps: Decimal = Decimal::ONE;
+    // let scheme = "1-sided";
+    let use_one_sided: Vec<bool> = vec![true; h.len()];
+    let all_inf = lb.iter().zip(ub.iter()).all(|(&lb_val, &ub_val)| lb_val == -Decimal::MAX && ub_val == Decimal::MAX);
+    if all_inf {
+       return (h, use_one_sided);
+    }
+
+    let h_total: Vec<Decimal> = h.iter().map(|&d| d * num_steps).collect();
+    let mut h_adjusted = h.clone();
+    let lower_dist: Vec<Decimal> = x0.iter().zip(lb.iter()).map(|(&x0_val, &lb_val)| x0_val - lb_val).collect();
+    let upper_dist: Vec<Decimal> = ub.iter().zip(x0.iter()).map(|(&ub_val, &x0_val)| {
+        if ub_val == Decimal::MAX{
+            Decimal::MAX
+        }else {
+            ub_val - x0_val
+        }
+    }).collect();
+
+    let x: Vec<Decimal> = x0.iter().zip(h_total.iter()).map(|(&d1, &d2)| d1 + d2).collect();
+    let violated_lb: Vec<bool> = x.iter().zip(lb.iter()).map(|(&x_val, &lb_val)| x_val < lb_val).collect();
+    let violated_ub: Vec<bool> = x.iter().zip(ub.iter()).map(|(&x_val, &ub_val)| x_val > ub_val).collect();
+    let violated: Vec<bool> = violated_lb.iter().zip(violated_ub.iter()).map(|(&vl_val, &vu_val)| vl_val | vu_val).collect();
+    let max_arr: Vec<Decimal> = lower_dist.iter().zip(upper_dist.iter()).map(|(&lower_val, &upper_val)|  upper_val.max(lower_val)).collect();
+    let abs_h_total: Vec<Decimal> = h_total.iter().map(|&h| h.abs()).collect();
+    let fitting: Vec<bool> = abs_h_total.iter().zip(max_arr.iter()).map(|(&abs_val, &max_val)| abs_val <= max_val).collect();
+    for ((h, &v), &f) in h_adjusted.iter_mut().zip(&violated).zip(&fitting) {
+        if v && f {
+            *h = -*h;
+        }
+    }
+    let forward: Vec<bool> = upper_dist.iter()
+        .zip(&lower_dist)
+        .zip(&fitting)
+        .map(|((&u, &l), &f)| u >= l && !f)
+        .collect();
+
+    for ((h, &u), &f) in h_adjusted.iter_mut().zip(&upper_dist).zip(&forward) {
+        if f {
+            *h = u / num_steps;
+        }
+    }
+    let backward: Vec<bool> = upper_dist.iter()
+        .zip(&lower_dist)
+        .zip(&fitting)
+        .map(|((&u, &l), &f)| u < l && !f)
+        .collect();
+
+    for ((h, &u), &f) in h_adjusted.iter_mut().zip(&lower_dist).zip(&backward) {
+        if f {
+            *h = u / num_steps;
+        }
+    }
+
+    return (h_adjusted, use_one_sided);
+}
+
+fn compute_absolute_step(x0: Vec<Decimal>) -> Vec<Decimal>{
+
+    // sign_x0 = (x0 >= 0).astype(float) * 2 - 1
+    let sign_x0: Vec<Decimal> = x0.iter().map(|&x| if x >= Decimal::ZERO { Decimal::ONE } else { Decimal::from_str("-1").unwrap() }).collect();
+
+    // Define rstep
+    let rstep = eps_for_method();
+    // abs_step = rstep * sign_x0 * np.maximum(1.0, np.abs(x0))
+    let abs_step: Vec<Decimal> = sign_x0.iter().zip(x0.iter()).map(|(&sign, &x)| rstep * sign * std::cmp::max(Decimal::ONE, x.abs())).collect();
+    abs_step
+}
+
+fn eps_for_method() -> Decimal{
+    let eps = f64::EPSILON;
+    Decimal::from_f64(eps.sqrt()).unwrap()
+}
+
+
+pub fn aaa(a: Decimal, b: Decimal) -> Decimal{
+    return a + b;
+}
+
 #[cfg(test)]
 mod tests {
     use chrono::Utc;
+    use ndarray::Array1;
+    use rust_decimal::Decimal;
     use rust_decimal_macros::dec;
-    use crate::utils::{clip, equidistant_sequence, fix_amount, fix_price, generate_client_id};
+    use crate::utils::{aaa, clip, equidistant_sequence, fix_amount, fix_price, generate_client_id};
 
     #[test]
     fn clip_test() {
@@ -162,8 +407,10 @@ mod tests {
 
     #[test]
     fn equidistant_sequence_test() {
-        let arr = equidistant_sequence(0, 10, 1);
-        print!("{:?}", arr);
+        let v: Vec<Decimal> = vec![Decimal::from(1), Decimal::from(2), Decimal::from(3)];
+        let a = aaa(v[0], v[1]);
+        println!("{:?}", a);
+        println!("{:?}", v);
     }
 
 }