|
|
@@ -1,5 +1,7 @@
|
|
|
+use futures_channel::mpsc::UnboundedSender;
|
|
|
use std::cmp::{max, min};
|
|
|
use std::collections::HashMap;
|
|
|
+use std::collections::VecDeque;
|
|
|
use std::ops::{Div, Mul};
|
|
|
use std::str::FromStr;
|
|
|
use chrono::Utc;
|
|
|
@@ -103,6 +105,10 @@ pub struct Strategy {
|
|
|
// 速度限制,至少0.5秒才取消订单
|
|
|
pub prev_place_order_timestamp: i64, // 上次挂单的时间
|
|
|
pub min_cancel_interval_mills: i64, // 至少要挂这么久才允许撤销
|
|
|
+
|
|
|
+
|
|
|
+ pub prev_insert_time: Decimal,
|
|
|
+ pub debug_sender: UnboundedSender<Vec<Decimal>>,
|
|
|
}
|
|
|
|
|
|
impl Strategy {
|
|
|
@@ -111,6 +117,49 @@ impl Strategy {
|
|
|
error!("参考盘口数不等于参考品种数,退出,请检查配置!");
|
|
|
panic!("参考盘口数不等于参考品种数,退出,请检查配置!");
|
|
|
}
|
|
|
+
|
|
|
+ // 创建数据通道
|
|
|
+ // 创建一个无界通道
|
|
|
+ let (tx, mut rx) = futures_channel::mpsc::unbounded::<Vec<Decimal>>();
|
|
|
+
|
|
|
+ tokio::spawn(async move {
|
|
|
+ let len = 16usize;
|
|
|
+ let mut prev_save_time = Decimal::from(Utc::now().timestamp_millis());
|
|
|
+ let mut debugs: Vec<VecDeque<Option<Decimal>>> = vec![VecDeque::new(); len];
|
|
|
+
|
|
|
+ while let Some(value) = rx.next().await {
|
|
|
+ // 数据填充到对应位置
|
|
|
+ for i in 0..len {
|
|
|
+ if value[i] == Decimal::from_str("14142135623730951").unwrap() {
|
|
|
+ debugs[i].push_back(None);
|
|
|
+ } else {
|
|
|
+ debugs[i].push_back(Some(value[i]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 长度限制
|
|
|
+ if debugs[0].len() > 500_000 {
|
|
|
+ for i in 0..len {
|
|
|
+ debugs[i].pop_front(); // 从前面移除元素
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let now = Decimal::from(Utc::now().timestamp_millis());
|
|
|
+ if now - prev_save_time < Decimal::from_str("60000").unwrap() {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ let debugs_clone = debugs.clone();
|
|
|
+ let temp_html_str = tokio::task::spawn_blocking(move || {
|
|
|
+ utils::build_html_file(&debugs_clone)
|
|
|
+ }).await.unwrap();
|
|
|
+
|
|
|
+ utils::write_to_file(&temp_html_str, "./db/db.html".to_string()).await;
|
|
|
+ prev_save_time = Decimal::from(Utc::now().timestamp_millis());
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+
|
|
|
// strategy的初始化,里面已经有一些参数初始化了
|
|
|
let mut strategy = Self {
|
|
|
_print_time: 0,
|
|
|
@@ -195,6 +244,8 @@ impl Strategy {
|
|
|
grid: Decimal::from(params.grid),
|
|
|
prev_place_order_timestamp: 0,
|
|
|
min_cancel_interval_mills: 500,
|
|
|
+ prev_insert_time: Default::default(),
|
|
|
+ debug_sender: tx,
|
|
|
};
|
|
|
|
|
|
// 交易名字
|
|
|
@@ -1267,70 +1318,82 @@ impl Strategy {
|
|
|
if command.limits_open.len() != 0 {
|
|
|
self.prev_place_order_timestamp = Utc::now().timestamp_millis();
|
|
|
}
|
|
|
+ command
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ async fn processor(&mut self) {
|
|
|
+ self.update_t_diff();
|
|
|
+ self.update_sigma_square();
|
|
|
+ self.update_gamma();
|
|
|
+ self.update_kappa();
|
|
|
+ self.update_delta();
|
|
|
+ self.update_optimal_ask_and_bid();
|
|
|
+
|
|
|
+ self.check_ready();
|
|
|
+ if !self.is_ready {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- // if command.limits_open.len() != 0 || command.limits_close.len() != 0 {
|
|
|
- // let name = self.params.account_name.clone();
|
|
|
- // // 参考卖价
|
|
|
- // let ref_ap = self.ref_ap;
|
|
|
- // // 参考买价
|
|
|
- // let ref_bp = self.ref_bp;
|
|
|
- // let limits_open = command.limits_open.clone();
|
|
|
- // let limits_close = command.limits_close.clone();
|
|
|
- // spawn(async move {
|
|
|
- // let time = chrono::Utc::now().timestamp_millis();
|
|
|
- // let param_list = paras_limit_command(name.clone(), time.clone(), ref_ap.clone(), ref_bp.clone(), limits_open, limits_close);
|
|
|
- // let param_json_obj = serde_json::to_string(¶m_list).unwrap();
|
|
|
- // market_warehouse_request(param_json_obj).await;
|
|
|
- // });
|
|
|
+ // let mut smm = Decimal::ZERO;
|
|
|
+ // if !self.depth_vec[1].time.is_zero() {
|
|
|
+ // let sma = self.depth_vec[1].asks[0].price;
|
|
|
+ // let smb = self.depth_vec[1].bids[0].price;
|
|
|
+ // smm = (sma + smb) / Decimal::TWO;
|
|
|
// }
|
|
|
|
|
|
- command
|
|
|
+
|
|
|
+ // let cci_arc = self.cci_arc.clone();
|
|
|
+ let now = Decimal::from_i64(Utc::now().timestamp_millis()).unwrap();
|
|
|
+ let mid_price = self.mid_price;
|
|
|
+ let ask_price = self.ask_price;
|
|
|
+ let bid_price = self.bid_price;
|
|
|
+ let last_price = self.last_price;
|
|
|
+
|
|
|
+ let spread = self.mid_price;
|
|
|
+ let spread_max = self.optimal_ask_price;
|
|
|
+ let spread_min = self.optimal_bid_price;
|
|
|
+ // let spread = self.price_times_avg;
|
|
|
+ // let spread_max = self.fair_price_vec[1] / self.fair_price_vec[0];
|
|
|
+ // let spread_min = self.fair_price / self.mid_price;
|
|
|
+
|
|
|
+ let optimal_ask_price = self.optimal_ask_price;
|
|
|
+ let optimal_bid_price = self.optimal_bid_price;
|
|
|
+
|
|
|
+ let inventory = self.inventory;
|
|
|
+ let sigma_square = if self.is_regressed { Decimal::ONE } else { Decimal::ZERO };
|
|
|
+ let gamma = now - self.last_update_time;
|
|
|
+ let kappa = self.fair_price / self.mid_price;
|
|
|
+
|
|
|
+ let flow_ratio = Decimal::ZERO;
|
|
|
+ let ref_price = self.fair_price;
|
|
|
+
|
|
|
+ let need_append = now - self.prev_insert_time > Decimal::ONE_HUNDRED;
|
|
|
+ if !need_append {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ self.debug_sender.unbounded_send(vec![
|
|
|
+ now,
|
|
|
+ mid_price,
|
|
|
+ ask_price,
|
|
|
+ bid_price,
|
|
|
+ last_price,
|
|
|
+ spread,
|
|
|
+ spread_max,
|
|
|
+ spread_min,
|
|
|
+ optimal_ask_price,
|
|
|
+ optimal_bid_price,
|
|
|
+ inventory,
|
|
|
+ sigma_square,
|
|
|
+ gamma,
|
|
|
+ kappa,
|
|
|
+ flow_ratio,
|
|
|
+ ref_price
|
|
|
+ ]).unwrap();
|
|
|
+
|
|
|
+ self.prev_insert_time = Decimal::from(Utc::now().timestamp_millis())
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// async fn market_warehouse_request(body_params: String) {
|
|
|
-// /****请求接口与 地址*/
|
|
|
-// let url = "http://as.skyfffire.com:8848/basic/saveDealRecords";
|
|
|
-//
|
|
|
-// let client = Client::new();
|
|
|
-// let req = client.post(url).header("auth", "43626546liangjiang")
|
|
|
-// .header("Content-Type", "application/json").body(body_params.clone());
|
|
|
-//
|
|
|
-// match req.send().await {
|
|
|
-// Ok(_) => {}
|
|
|
-// Err(_) => {}
|
|
|
-// };
|
|
|
-// // if !response.status().is_success() {
|
|
|
-// // error!("行情数据------仓库挂单数据存储失败--------!{}", response.status());
|
|
|
-// // error!(body_params);
|
|
|
-// // }
|
|
|
-// }
|
|
|
-//
|
|
|
-// fn paras_limit_command (robot_name: String, time: i64, ref_ap: Decimal, ref_bp: Decimal, limits_open: HashMap<String, Vec<String>>, limits_close: HashMap<String, Vec<String>>) -> Vec<DealRecord>{
|
|
|
-// let mut limits = HashMap::new();
|
|
|
-// limits.extend(limits_open);
|
|
|
-// limits.extend(limits_close);
|
|
|
-// let mut list: Vec<DealRecord> = Vec::with_capacity(limits.len());
|
|
|
-// for item in limits.keys() {
|
|
|
-// let item_clone = item.clone();
|
|
|
-// let value = limits[&item_clone].clone();
|
|
|
-// let amount = Decimal::from_str(value.get(0).unwrap_or(&"0".to_string())).unwrap();
|
|
|
-// let side = value.get(1).unwrap();
|
|
|
-// let price = Decimal::from_str(value.get(2).unwrap_or(&"0".to_string())).unwrap();
|
|
|
-// let mut ref_price = ref_ap;
|
|
|
-// if "kd" == side {
|
|
|
-// ref_price = ref_bp;
|
|
|
-// }
|
|
|
-// let deal_recode = DealRecord {
|
|
|
-// refPrice: ref_price.to_string(),
|
|
|
-// regPrice: price.to_string(),
|
|
|
-// num: amount.to_string(),
|
|
|
-// triggerTime: time,
|
|
|
-// robotName: robot_name.clone(),
|
|
|
-// side: side.to_string(),
|
|
|
-// };
|
|
|
-// list.push(deal_recode);
|
|
|
-// }
|
|
|
-// return list;
|
|
|
-// }
|
|
|
|