|
|
@@ -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);
|
|
|
}
|
|
|
|
|
|
}
|