|
|
@@ -1,4 +1,4 @@
|
|
|
-use std::cmp::{max, min};
|
|
|
+use std::cmp::{min};
|
|
|
use std::collections::HashMap;
|
|
|
use rust_decimal::{Decimal, MathematicalOps};
|
|
|
use rust_decimal_macros::dec;
|
|
|
@@ -25,8 +25,10 @@ pub struct Rank {
|
|
|
is_binance: bool,
|
|
|
}
|
|
|
|
|
|
+const ONE_QUARTER: Decimal = dec!(0.25);
|
|
|
+const ONE_PERCENT: Decimal = dec!(0.01);
|
|
|
const TWENTY: Decimal = dec!(20);
|
|
|
-const SIXTY: Decimal = dec!(60);
|
|
|
+// const SIXTY: Decimal = dec!(60);
|
|
|
const TWO_HUNDRED: Decimal = dec!(200);
|
|
|
// const TEN_THOUSAND: Decimal = dec!(10000);
|
|
|
|
|
|
@@ -40,79 +42,76 @@ pub fn generate_rank_by_indicator_map(indicator_map: &MutexGuard<HashMap<String,
|
|
|
// ============== msv相关数据的计算 =================
|
|
|
let mut msv_abs_total = Decimal::ZERO;
|
|
|
let mut msv_abs_max = Decimal::ZERO;
|
|
|
- let mut effective_count = Decimal::ZERO;
|
|
|
- let mut effective_msv_vec: Vec<Decimal> = vec![];
|
|
|
- for value in indicators.msv.iter() {
|
|
|
+ let mut msv_count = Decimal::ZERO;
|
|
|
+ let mut effective_epr_count = Decimal::ZERO;
|
|
|
+ for (index, value) in indicators.msv.iter().enumerate() {
|
|
|
let msv_abs_value = value[1].abs();
|
|
|
|
|
|
if msv_abs_value <= Decimal::ZERO {
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- effective_count += Decimal::ONE;
|
|
|
+ msv_count += Decimal::ONE;
|
|
|
msv_abs_total += msv_abs_value;
|
|
|
- effective_msv_vec.push(msv_abs_value);
|
|
|
|
|
|
if msv_abs_value > msv_abs_max {
|
|
|
msv_abs_max = msv_abs_value
|
|
|
}
|
|
|
+
|
|
|
+ let epr = &indicators.eprs[index];
|
|
|
+ if epr[1] > msv_abs_value * ONE_QUARTER {
|
|
|
+ effective_epr_count += Decimal::ONE;
|
|
|
+ }
|
|
|
}
|
|
|
// 计算波动率平均值
|
|
|
- let mut msv_abs_avg = if effective_count == Decimal::ZERO {
|
|
|
+ let mut msv_abs_avg = if msv_count == Decimal::ZERO {
|
|
|
Decimal::ZERO
|
|
|
} else {
|
|
|
- msv_abs_total / effective_count
|
|
|
+ msv_abs_total / msv_count
|
|
|
};
|
|
|
msv_abs_avg.rescale(6);
|
|
|
- // 计算方差
|
|
|
- let msv_variance = if effective_count == Decimal::ZERO {
|
|
|
- Decimal::ZERO
|
|
|
- } else {
|
|
|
- let mut total = Decimal::ZERO;
|
|
|
-
|
|
|
- for effective_msv in effective_msv_vec {
|
|
|
- total += (effective_msv - msv_abs_avg).powd(Decimal::TWO)
|
|
|
- }
|
|
|
-
|
|
|
- total / effective_count
|
|
|
- };
|
|
|
- // 标准差
|
|
|
- let standard_deviation = msv_variance.sqrt().unwrap();
|
|
|
- let mut coverted_open_base = (msv_abs_max + standard_deviation) / TWO_HUNDRED;
|
|
|
- coverted_open_base = max(coverted_open_base, Decimal::ZERO);
|
|
|
+ // 开仓基准值, 除以200是先除以2,再除以100(因为系统开仓参数是0.01代表1%)
|
|
|
+ let mut coverted_open_base = (msv_abs_max + msv_abs_avg) / TWO_HUNDRED;
|
|
|
coverted_open_base.rescale(8);
|
|
|
|
|
|
// ============== epr相关数据的计算 =================
|
|
|
let mut epr_total = Decimal::ZERO;
|
|
|
let mut epr_max = Decimal::ZERO;
|
|
|
+ // let mut epr_count = Decimal::ZERO;
|
|
|
for value in indicators.eprs.iter() {
|
|
|
+ if value[1].abs() < ONE_PERCENT {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
epr_total += value[1];
|
|
|
+ // epr_count += Decimal::ONE;
|
|
|
|
|
|
if value[1] > epr_max {
|
|
|
epr_max = value[1]
|
|
|
}
|
|
|
}
|
|
|
+ // let epr_avg = if epr_count == Decimal::ZERO {
|
|
|
+ // epr_total
|
|
|
+ // } else {
|
|
|
+ // epr_total / epr_count
|
|
|
+ // };
|
|
|
|
|
|
// ============== liq相关数据的计算 =================
|
|
|
let mut liquidity_total = Decimal::ZERO;
|
|
|
for value in indicators.liqs.iter() {
|
|
|
liquidity_total += value[1] * Decimal::ONE_THOUSAND;
|
|
|
}
|
|
|
- let mut liquidity_avg = if effective_count == Decimal::ZERO {
|
|
|
+ let mut liquidity_avg = if msv_count == Decimal::ZERO {
|
|
|
Decimal::ZERO
|
|
|
} else {
|
|
|
- liquidity_total / effective_count
|
|
|
+ liquidity_total / msv_count
|
|
|
};
|
|
|
liquidity_avg.rescale(0);
|
|
|
|
|
|
// ======================== 最终计算 =========================
|
|
|
// msv_score计算规则
|
|
|
let mut msv_score = if msv_abs_total > Decimal::ZERO && epr_total > Decimal::ZERO {
|
|
|
- if epr_total > msv_abs_total {
|
|
|
- (epr_max * SIXTY).powd(Decimal::TWO)
|
|
|
- } else {
|
|
|
- ((epr_max * epr_total / msv_abs_total) * SIXTY).powd(Decimal::TWO)
|
|
|
- }
|
|
|
+ epr_total * (epr_total / msv_abs_total)
|
|
|
} else {
|
|
|
Decimal::ZERO
|
|
|
};
|
|
|
@@ -123,7 +122,7 @@ pub fn generate_rank_by_indicator_map(indicator_map: &MutexGuard<HashMap<String,
|
|
|
liquidity_score.rescale(2);
|
|
|
|
|
|
// frequency_score计算规则
|
|
|
- let mut frequency_score = ((effective_count / Decimal::ONE_THOUSAND) * TWENTY).sqrt().unwrap();
|
|
|
+ let mut frequency_score = ((effective_epr_count / Decimal::ONE_THOUSAND) * TWENTY).sqrt().unwrap();
|
|
|
frequency_score.rescale(2);
|
|
|
|
|
|
let temp = msv_score * liquidity_score * frequency_score;
|
|
|
@@ -145,7 +144,7 @@ pub fn generate_rank_by_indicator_map(indicator_map: &MutexGuard<HashMap<String,
|
|
|
msv_abs_avg,
|
|
|
coverted_open_base,
|
|
|
epr_total,
|
|
|
- effective_count,
|
|
|
+ effective_count: msv_count,
|
|
|
liquidity_avg,
|
|
|
is_binance,
|
|
|
};
|