|
@@ -104,26 +104,29 @@ pub async fn generate_msv(query_value: Value) -> HttpResponse {
|
|
|
|
|
|
|
|
// 将trades转换为具体指标
|
|
// 将trades转换为具体指标
|
|
|
pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simple_depths: Vec<SimpleDepth>, start_time: i64, end_time: i64) -> Value {
|
|
pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simple_depths: Vec<SimpleDepth>, start_time: i64, end_time: i64) -> Value {
|
|
|
|
|
+ // 具体波动
|
|
|
let mut msv_data: Vec<Vec<Decimal>> = vec![];
|
|
let mut msv_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
+ // 预期利润幅度(except_profit_rate)
|
|
|
|
|
+ let mut epr_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
|
|
|
const GAMMA: Decimal = dec!(0.5);
|
|
const GAMMA: Decimal = dec!(0.5);
|
|
|
|
|
|
|
|
- // 每一个元素都遍历一遍
|
|
|
|
|
|
|
+ // ================== 计算每个点的具体波动率以及回溯幅度 ===================
|
|
|
trades.sort_by(|a, b| Decimal::from_str(a.id.as_str()).unwrap().cmp(&Decimal::from_str(b.id.as_str()).unwrap()));
|
|
trades.sort_by(|a, b| Decimal::from_str(a.id.as_str()).unwrap().cmp(&Decimal::from_str(b.id.as_str()).unwrap()));
|
|
|
for (index, trade) in trades.iter().enumerate() {
|
|
for (index, trade) in trades.iter().enumerate() {
|
|
|
|
|
+ if index == 0 {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 该元素向前遍历range毫秒
|
|
// 该元素向前遍历range毫秒
|
|
|
- let mut range_index = if index == 0 {
|
|
|
|
|
- 0
|
|
|
|
|
- } else {
|
|
|
|
|
- index
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ let mut range_index = index;
|
|
|
|
|
|
|
|
// 计算区间的预定价格
|
|
// 计算区间的预定价格
|
|
|
let mut ref_price = trade.price;
|
|
let mut ref_price = trade.price;
|
|
|
let mut dissociation = Decimal::ZERO;
|
|
let mut dissociation = Decimal::ZERO;
|
|
|
loop {
|
|
loop {
|
|
|
- // 第0个就不搞
|
|
|
|
|
- if range_index == 0 {
|
|
|
|
|
|
|
+ // 下标合法性判断
|
|
|
|
|
+ if range_index <= 0 {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -140,51 +143,80 @@ pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simpl
|
|
|
range_index -= 1;
|
|
range_index -= 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 逻辑计算层
|
|
|
|
|
- // 取离当前点最远的点进行测量
|
|
|
|
|
- let last_price = trade.price;
|
|
|
|
|
-
|
|
|
|
|
- // 不是初始值,以及不是0波动
|
|
|
|
|
- if index != 0 {
|
|
|
|
|
- let mut rate = Decimal::ONE_HUNDRED * (last_price - ref_price) / ref_price;
|
|
|
|
|
|
|
+ // 获取到range毫秒以后的预定价格,计算回去的幅度
|
|
|
|
|
+ let mut future_ref_price = ref_price;
|
|
|
|
|
+ let mut future_range_index = index;
|
|
|
|
|
+ loop {
|
|
|
|
|
+ // 下标合法性判断
|
|
|
|
|
+ if future_range_index >= trades.len() {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- rate.rescale(2);
|
|
|
|
|
|
|
+ let flag_trade = trades.get(range_index).unwrap();
|
|
|
|
|
+ let range_time = flag_trade.time - trade.time;
|
|
|
|
|
|
|
|
- // 去除小数位之后,可以忽略一些太小的波动,减少图表生成压力
|
|
|
|
|
- if rate.eq(&Decimal::ZERO) {
|
|
|
|
|
- continue
|
|
|
|
|
|
|
+ // 判断该ticker是否是range ms以外
|
|
|
|
|
+ if range_time > mills_back {
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
|
|
+ future_ref_price = future_ref_price * GAMMA + flag_trade.price * (Decimal::ONE - GAMMA);
|
|
|
|
|
+
|
|
|
|
|
+ future_range_index += 1;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 去重,以及保留最大的波动率
|
|
|
|
|
- if msv_data.len() > 0 {
|
|
|
|
|
- let last = msv_data[msv_data.len() - 1].clone();
|
|
|
|
|
- let last_time = last[0];
|
|
|
|
|
- let last_rate = last[1];
|
|
|
|
|
-
|
|
|
|
|
- // 如果时间相同,则可能会进行remove等操作
|
|
|
|
|
- if last_time == trade.time {
|
|
|
|
|
- // 如果最新的波动率大于最后波动率
|
|
|
|
|
- if rate.abs() > last_rate.abs() {
|
|
|
|
|
- msv_data.remove(msv_data.len() - 1);
|
|
|
|
|
- msv_data.push(vec![trade.time, rate, dissociation]);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+ let last_price = trade.price;
|
|
|
|
|
+ // ==================== 波动逻辑计算 ====================
|
|
|
|
|
+ let mut rate = Decimal::ONE_HUNDRED * (last_price - ref_price) / ref_price;
|
|
|
|
|
+ rate.rescale(2);
|
|
|
|
|
+ // 去除小数位之后,可以忽略一些太小的波动,减少图表生成压力
|
|
|
|
|
+ if rate.eq(&Decimal::ZERO) {
|
|
|
|
|
+ continue
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ==================== 预期利润逻辑计算 ====================
|
|
|
|
|
+ // 首先计算未来一段时间的价格与现在的距离
|
|
|
|
|
+ let mut future_rate = Decimal::ONE_HUNDRED * (future_ref_price - last_price) / last_price;
|
|
|
|
|
+ future_rate.rescale(2);
|
|
|
|
|
+ // 根据具体向上波动还是向下波动来计算预期最大利润
|
|
|
|
|
+ let epr = if rate > Decimal::ZERO {
|
|
|
|
|
+ -future_rate
|
|
|
|
|
+ } else {
|
|
|
|
|
+ future_rate
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 去重,以及保留最大的波动率
|
|
|
|
|
+ if msv_data.len() > 0 {
|
|
|
|
|
+ let last = msv_data[msv_data.len() - 1].clone();
|
|
|
|
|
+ let last_time = last[0];
|
|
|
|
|
+ let last_rate = last[1];
|
|
|
|
|
+
|
|
|
|
|
+ // 如果时间相同,则可能会进行remove等操作
|
|
|
|
|
+ if last_time == trade.time {
|
|
|
|
|
+ // 如果最新的波动率大于最后波动率
|
|
|
|
|
+ if rate.abs() > last_rate.abs() {
|
|
|
|
|
+ msv_data.remove(msv_data.len() - 1);
|
|
|
msv_data.push(vec![trade.time, rate, dissociation]);
|
|
msv_data.push(vec![trade.time, rate, dissociation]);
|
|
|
|
|
+
|
|
|
|
|
+ epr_data.remove(epr_data.len() - 1);
|
|
|
|
|
+ epr_data.push(vec![trade.time, epr]);
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
msv_data.push(vec![trade.time, rate, dissociation]);
|
|
msv_data.push(vec![trade.time, rate, dissociation]);
|
|
|
|
|
+ epr_data.push(vec![trade.time, epr]);
|
|
|
}
|
|
}
|
|
|
|
|
+ } else {
|
|
|
|
|
+ msv_data.push(vec![trade.time, rate, dissociation]);
|
|
|
|
|
+ epr_data.push(vec![trade.time, epr]);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 按时间序列填充数据
|
|
// 按时间序列填充数据
|
|
|
let mut msv_index = 0;
|
|
let mut msv_index = 0;
|
|
|
let mut final_msv_data: Vec<Vec<Decimal>> = vec![];
|
|
let mut final_msv_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
+ let mut final_epr_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
|
|
|
let mut depth_index = 0;
|
|
let mut depth_index = 0;
|
|
|
- let mut final_depth_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
-
|
|
|
|
|
- let final_spread_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
|
|
+ let mut final_volume_data: Vec<Vec<Decimal>> = vec![];
|
|
|
|
|
|
|
|
let mut index_timestamp = Decimal::from_i64(start_time).unwrap();
|
|
let mut index_timestamp = Decimal::from_i64(start_time).unwrap();
|
|
|
let last_timestamp = Decimal::from_i64(end_time).unwrap();
|
|
let last_timestamp = Decimal::from_i64(end_time).unwrap();
|
|
@@ -192,6 +224,7 @@ pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simpl
|
|
|
loop {
|
|
loop {
|
|
|
let mut max_msv_data = Decimal::ZERO;
|
|
let mut max_msv_data = Decimal::ZERO;
|
|
|
let mut max_msv_qty_data = Decimal::ZERO;
|
|
let mut max_msv_qty_data = Decimal::ZERO;
|
|
|
|
|
+ let mut max_epr_data = Decimal::ZERO;
|
|
|
|
|
|
|
|
// ====================================== 数据生产 ===============================================
|
|
// ====================================== 数据生产 ===============================================
|
|
|
// 获取时间范围内的波动率数据
|
|
// 获取时间范围内的波动率数据
|
|
@@ -209,11 +242,16 @@ pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simpl
|
|
|
// -------------- 大小判断,取值
|
|
// -------------- 大小判断,取值
|
|
|
let msv_d = msv_data[msv_index][1];
|
|
let msv_d = msv_data[msv_index][1];
|
|
|
let msv_qty_data = msv_data[msv_index][2];
|
|
let msv_qty_data = msv_data[msv_index][2];
|
|
|
|
|
+ let epr_data = msv_data[msv_index][2];
|
|
|
// msv波动数据
|
|
// msv波动数据
|
|
|
if max_msv_data.abs() < msv_d.abs() {
|
|
if max_msv_data.abs() < msv_d.abs() {
|
|
|
max_msv_data = msv_d;
|
|
max_msv_data = msv_d;
|
|
|
max_msv_qty_data = msv_qty_data;
|
|
max_msv_qty_data = msv_qty_data;
|
|
|
}
|
|
}
|
|
|
|
|
+ // epr数据
|
|
|
|
|
+ if max_epr_data.abs() < epr_data.abs() {
|
|
|
|
|
+ max_epr_data = epr_data;
|
|
|
|
|
+ }
|
|
|
// 下标步近
|
|
// 下标步近
|
|
|
msv_index = msv_index + 1;
|
|
msv_index = msv_index + 1;
|
|
|
}
|
|
}
|
|
@@ -268,15 +306,17 @@ pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simpl
|
|
|
// 如果这两个值为0,则代表这mills_back毫秒以内是没有数据的,填充0数据,使得x轴是完整的
|
|
// 如果这两个值为0,则代表这mills_back毫秒以内是没有数据的,填充0数据,使得x轴是完整的
|
|
|
if max_msv_data == Decimal::ZERO {
|
|
if max_msv_data == Decimal::ZERO {
|
|
|
final_msv_data.push(vec![index_timestamp, Decimal::ZERO, Decimal::ZERO]);
|
|
final_msv_data.push(vec![index_timestamp, Decimal::ZERO, Decimal::ZERO]);
|
|
|
- final_depth_data.push(vec![index_timestamp, Decimal::ZERO]);
|
|
|
|
|
|
|
+ final_epr_data.push(vec![index_timestamp, Decimal::ZERO]);
|
|
|
|
|
+ final_volume_data.push(vec![index_timestamp, Decimal::ZERO]);
|
|
|
|
|
|
|
|
// 说明在这个时间范围内是有数据存在的,将推动行情的流动性放入副图
|
|
// 说明在这个时间范围内是有数据存在的,将推动行情的流动性放入副图
|
|
|
} else {
|
|
} else {
|
|
|
final_msv_data.push(vec![index_timestamp, max_msv_data, max_msv_qty_data]);
|
|
final_msv_data.push(vec![index_timestamp, max_msv_data, max_msv_qty_data]);
|
|
|
|
|
+ final_epr_data.push(vec![index_timestamp, max_epr_data]);
|
|
|
|
|
|
|
|
let mut final_qty = max_msv_qty_data / Decimal::ONE_THOUSAND;
|
|
let mut final_qty = max_msv_qty_data / Decimal::ONE_THOUSAND;
|
|
|
final_qty.rescale(2);
|
|
final_qty.rescale(2);
|
|
|
- final_depth_data.push(vec![index_timestamp, final_qty]);
|
|
|
|
|
|
|
+ final_volume_data.push(vec![index_timestamp, final_qty]);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ====================================== 时间步进处理 ======================================
|
|
// ====================================== 时间步进处理 ======================================
|
|
@@ -293,8 +333,8 @@ pub fn generate_msv_by_trades(mut trades: Vec<Trade>, mills_back: Decimal, simpl
|
|
|
let result_size = final_msv_data.len();
|
|
let result_size = final_msv_data.len();
|
|
|
json!({
|
|
json!({
|
|
|
"msv": final_msv_data,
|
|
"msv": final_msv_data,
|
|
|
- "liqs": final_depth_data,
|
|
|
|
|
- "spreads": final_spread_data,
|
|
|
|
|
|
|
+ "liqs": final_volume_data,
|
|
|
|
|
+ "epr": final_epr_data,
|
|
|
"total_size": total_size,
|
|
"total_size": total_size,
|
|
|
"result_size": result_size,
|
|
"result_size": result_size,
|
|
|
})
|
|
})
|