|
|
@@ -24,6 +24,7 @@ use global::trade::Trade;
|
|
|
use standard::{Account, Market, Order, OrderCommand, Platform, Position, PositionModeEnum, SpecialTicker, Ticker};
|
|
|
use standard::exchange::{Exchange};
|
|
|
use standard::exchange::ExchangeEnum::{BinanceSwap, BitgetSwap, BybitSwap, CoinexSwap, GateSwap, HtxSwap, KucoinSwap};
|
|
|
+use standard::handle_info::DepthParam;
|
|
|
use crate::fix_price::PricingEngine;
|
|
|
use crate::model::{LocalPosition, OrderInfo, TokenParam};
|
|
|
use crate::predictor::Predictor;
|
|
|
@@ -126,6 +127,7 @@ pub struct Core {
|
|
|
pub is_sigma_allow_open: bool, // 是否允许开单
|
|
|
|
|
|
pub trading_volume: Decimal, // 交易量统计
|
|
|
+ pub last_ref_price: Decimal, // 最后一次进入挂单的参考价格
|
|
|
}
|
|
|
|
|
|
impl Core {
|
|
|
@@ -269,6 +271,7 @@ impl Core {
|
|
|
is_sigma_abnormal: false,
|
|
|
is_sigma_allow_open: true,
|
|
|
trading_volume: Default::default(),
|
|
|
+ last_ref_price: Default::default(),
|
|
|
};
|
|
|
for i in 0..=params.ref_exchange.len() - 1 {
|
|
|
// 拼接不会消耗原字符串
|
|
|
@@ -681,6 +684,71 @@ impl Core {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ pub async fn on_ref_price_update(&mut self, name_ref: &String, ref_price: Decimal, trace_stack: &mut TraceStack){
|
|
|
+ let now_time = Utc::now().timestamp_millis();
|
|
|
+ self.market_update_time.insert(name_ref.clone(), now_time);
|
|
|
+ if ref_price == Decimal::ZERO{
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 过滤条件 价格变化很大 时间间隔很长
|
|
|
+ let mut flag = 0;
|
|
|
+
|
|
|
+ let price_rate = (ref_price - self.last_ref_price).abs() / ref_price;
|
|
|
+ let rate = dec!(0.0002);
|
|
|
+ // 验证这次获取的预定价格要比上次的预定价格相差0.0002以上并且距离上次进入开单的时间间隔 > 50
|
|
|
+ if price_rate > rate || Utc::now().timestamp_millis() - self.on_tick_event_time > 50 {
|
|
|
+ // 允许交易
|
|
|
+ flag = 1;
|
|
|
+ // 更新ontick触发时间记录
|
|
|
+ self.on_tick_event_time = Utc::now().timestamp_millis();
|
|
|
+ // // 全局记录一下最后的预定价格
|
|
|
+ self.last_ref_price = ref_price;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 允许交易
|
|
|
+ if self.mode_signal == 0 && self.ready == 1 && flag == 1 {
|
|
|
+ // 更新交易数据
|
|
|
+ self.update_trade_msg();
|
|
|
+ // 更新预定价格
|
|
|
+ self.ref_price = vec![vec![ref_price, ref_price]];
|
|
|
+ // 触发事件撤单逻辑
|
|
|
+ // 更新策略时间
|
|
|
+ self.strategy.local_time = Utc::now().timestamp_millis();
|
|
|
+
|
|
|
+ // 产生交易信号
|
|
|
+ let mut orders = self.strategy.on_tick(&self.local_orders,
|
|
|
+ &self.local_position_by_orders,
|
|
|
+ &self.agg_market,
|
|
|
+ &self.local_cash,
|
|
|
+ &self.local_coin,
|
|
|
+ &self.ref_price,
|
|
|
+ &self.predict,
|
|
|
+ &true,
|
|
|
+ &trace_stack.ins);
|
|
|
+ trace_stack.on_after_strategy();
|
|
|
+
|
|
|
+ if orders.is_not_empty() {
|
|
|
+ let mut platform_rest_fb = self.platform_rest.clone_box();
|
|
|
+ // 先更新本地记录再发单。
|
|
|
+ self._update_local_orders(&mut orders);
|
|
|
+ // info!("订单指令:{:?}", orders);
|
|
|
+ let mut ts = trace_stack.clone();
|
|
|
+ spawn(async move {
|
|
|
+ platform_rest_fb.command_order(&mut orders, &mut ts).await;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 更新中控账户相关信息
|
|
|
+ {
|
|
|
+ let mut now_balance = self.strategy.equity / self.used_pct;
|
|
|
+ now_balance.rescale(4);
|
|
|
+
|
|
|
+ let mut cci = self.cci_arc.lock().await;
|
|
|
+ cci.now_balance = now_balance;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// #[instrument(skip(self, depth, name_ref, trace_stack), level="TRACE")]
|
|
|
pub async fn on_depth_update(&mut self, depth: &Vec<Decimal>, name_ref: &String, trace_stack: &mut TraceStack) {
|
|
|
// 要从回调传入的深度信息中获取data.name
|
|
|
@@ -705,71 +773,71 @@ impl Core {
|
|
|
}
|
|
|
} else if *name_ref == self.ref_name[0] { // 判断是否为当前跟踪的盘口
|
|
|
// 写入行情数据
|
|
|
- let ticker = self.tickers.get(name_ref).unwrap();
|
|
|
- if self.trade_vec.len() == 100 {
|
|
|
- self.trade_vec.pop_front();
|
|
|
- }
|
|
|
- self.trade_vec.push_back(Trade::new_by_ticker(ticker.mid_price.clone(), ticker.create_at/1000));
|
|
|
- // 更新波动率
|
|
|
- if self.trade_vec.len() > 99 {
|
|
|
- self.calc_sigma();
|
|
|
- // 波动率正常,但还是不开单信号,允许开单
|
|
|
- if !self.is_sigma_abnormal && !self.is_sigma_allow_open {
|
|
|
- self.is_sigma_allow_open = true;
|
|
|
- }
|
|
|
- }
|
|
|
- // 判断是否需要触发ontick 对行情进行过滤
|
|
|
- // 过滤条件 价格变化很大 时间间隔很长
|
|
|
- let mut flag = 0;
|
|
|
- let bid_price_rate = (depth[BID_PRICE_INDEX] - self.depths.get(name_ref).unwrap()[BID_PRICE_INDEX]).abs() / depth[BID_PRICE_INDEX];
|
|
|
- let ask_price_rate = (depth[ASK_PRICE_INDEX] - self.depths.get(name_ref).unwrap()[ASK_PRICE_INDEX]).abs() / depth[ASK_PRICE_INDEX];
|
|
|
- let rate = dec!(0.0002);
|
|
|
- if bid_price_rate > rate || ask_price_rate > rate || Utc::now().timestamp_millis() - self.on_tick_event_time > 50 {
|
|
|
- // 允许交易
|
|
|
- flag = 1;
|
|
|
- // 更新ontick触发时间记录
|
|
|
- self.on_tick_event_time = Utc::now().timestamp_millis();
|
|
|
- }
|
|
|
- // 允许交易
|
|
|
- if self.mode_signal == 0 && self.ready == 1 && flag == 1 {
|
|
|
- // 更新交易数据
|
|
|
- self.update_trade_msg();
|
|
|
- // 触发事件撤单逻辑
|
|
|
- // 更新策略时间
|
|
|
- self.strategy.local_time = Utc::now().timestamp_millis();
|
|
|
-
|
|
|
- // 产生交易信号
|
|
|
- let mut orders = self.strategy.on_tick(&self.local_orders,
|
|
|
- &self.local_position_by_orders,
|
|
|
- &self.agg_market,
|
|
|
- &self.local_cash,
|
|
|
- &self.local_coin,
|
|
|
- &self.ref_price,
|
|
|
- &self.predict,
|
|
|
- &self.is_sigma_allow_open,
|
|
|
- &trace_stack.ins);
|
|
|
- trace_stack.on_after_strategy();
|
|
|
-
|
|
|
- if orders.is_not_empty() {
|
|
|
- let mut platform_rest_fb = self.platform_rest.clone_box();
|
|
|
- // 先更新本地记录再发单。
|
|
|
- self._update_local_orders(&mut orders);
|
|
|
- // info!("订单指令:{:?}", orders);
|
|
|
- let mut ts = trace_stack.clone();
|
|
|
- spawn(async move {
|
|
|
- platform_rest_fb.command_order(&mut orders, &mut ts).await;
|
|
|
- });
|
|
|
-
|
|
|
- // 更新中控账户相关信息
|
|
|
- {
|
|
|
- let mut now_balance = self.strategy.equity / self.used_pct;
|
|
|
- now_balance.rescale(4);
|
|
|
-
|
|
|
- let mut cci = self.cci_arc.lock().await;
|
|
|
- cci.now_balance = now_balance;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ // let ticker = self.tickers.get(name_ref).unwrap();
|
|
|
+ // if self.trade_vec.len() == 100 {
|
|
|
+ // self.trade_vec.pop_front();
|
|
|
+ // }
|
|
|
+ // self.trade_vec.push_back(Trade::new_by_ticker(ticker.mid_price.clone(), ticker.create_at/1000));
|
|
|
+ // // 更新波动率
|
|
|
+ // if self.trade_vec.len() > 99 {
|
|
|
+ // self.calc_sigma();
|
|
|
+ // // 波动率正常,但还是不开单信号,允许开单
|
|
|
+ // if !self.is_sigma_abnormal && !self.is_sigma_allow_open {
|
|
|
+ // self.is_sigma_allow_open = true;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // // 判断是否需要触发ontick 对行情进行过滤
|
|
|
+ // // 过滤条件 价格变化很大 时间间隔很长
|
|
|
+ // let mut flag = 0;
|
|
|
+ // let bid_price_rate = (depth[BID_PRICE_INDEX] - self.depths.get(name_ref).unwrap()[BID_PRICE_INDEX]).abs() / depth[BID_PRICE_INDEX];
|
|
|
+ // let ask_price_rate = (depth[ASK_PRICE_INDEX] - self.depths.get(name_ref).unwrap()[ASK_PRICE_INDEX]).abs() / depth[ASK_PRICE_INDEX];
|
|
|
+ // let rate = dec!(0.0002);
|
|
|
+ // if bid_price_rate > rate || ask_price_rate > rate || Utc::now().timestamp_millis() - self.on_tick_event_time > 50 {
|
|
|
+ // // 允许交易
|
|
|
+ // flag = 1;
|
|
|
+ // // 更新ontick触发时间记录
|
|
|
+ // self.on_tick_event_time = Utc::now().timestamp_millis();
|
|
|
+ // }
|
|
|
+ // // 允许交易
|
|
|
+ // if self.mode_signal == 0 && self.ready == 1 && flag == 1 {
|
|
|
+ // // 更新交易数据
|
|
|
+ // self.update_trade_msg();
|
|
|
+ // // 触发事件撤单逻辑
|
|
|
+ // // 更新策略时间
|
|
|
+ // self.strategy.local_time = Utc::now().timestamp_millis();
|
|
|
+ //
|
|
|
+ // // 产生交易信号
|
|
|
+ // let mut orders = self.strategy.on_tick(&self.local_orders,
|
|
|
+ // &self.local_position_by_orders,
|
|
|
+ // &self.agg_market,
|
|
|
+ // &self.local_cash,
|
|
|
+ // &self.local_coin,
|
|
|
+ // &self.ref_price,
|
|
|
+ // &self.predict,
|
|
|
+ // &self.is_sigma_allow_open,
|
|
|
+ // &trace_stack.ins);
|
|
|
+ // trace_stack.on_after_strategy();
|
|
|
+ //
|
|
|
+ // if orders.is_not_empty() {
|
|
|
+ // let mut platform_rest_fb = self.platform_rest.clone_box();
|
|
|
+ // // 先更新本地记录再发单。
|
|
|
+ // self._update_local_orders(&mut orders);
|
|
|
+ // // info!("订单指令:{:?}", orders);
|
|
|
+ // let mut ts = trace_stack.clone();
|
|
|
+ // spawn(async move {
|
|
|
+ // platform_rest_fb.command_order(&mut orders, &mut ts).await;
|
|
|
+ // });
|
|
|
+ //
|
|
|
+ // // 更新中控账户相关信息
|
|
|
+ // {
|
|
|
+ // let mut now_balance = self.strategy.equity / self.used_pct;
|
|
|
+ // now_balance.rescale(4);
|
|
|
+ //
|
|
|
+ // let mut cci = self.cci_arc.lock().await;
|
|
|
+ // cci.now_balance = now_balance;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
}
|
|
|
|
|
|
{
|
|
|
@@ -933,21 +1001,22 @@ impl Core {
|
|
|
// self.trade_msg.position = self.local_position_by_orders.clone();
|
|
|
// self.trade_msg.orders = self.local_orders.clone();
|
|
|
// 更新 ref
|
|
|
- let mut ref_tickers: BTreeMap<String, Ticker> = BTreeMap::new();
|
|
|
- for i in &self.ref_name {
|
|
|
- let bp = self.tickers.get(i).unwrap().buy;
|
|
|
- let ap = self.tickers.get(i).unwrap().sell;
|
|
|
- ref_tickers.insert(i.clone(), Ticker {
|
|
|
- time: 0,
|
|
|
- high: Default::default(),
|
|
|
- low: Default::default(),
|
|
|
- sell: ap,
|
|
|
- buy: bp,
|
|
|
- last: Default::default(),
|
|
|
- volume: Default::default(),
|
|
|
- });
|
|
|
- }
|
|
|
- self.ref_price = self.predictor.get_ref_price(&ref_tickers);
|
|
|
+ // let mut ref_tickers: BTreeMap<String, Ticker> = BTreeMap::new();
|
|
|
+ // for i in &self.ref_name {
|
|
|
+ // let bp = self.tickers.get(i).unwrap().buy;
|
|
|
+ // let ap = self.tickers.get(i).unwrap().sell;
|
|
|
+ // ref_tickers.insert(i.clone(), Ticker {
|
|
|
+ // time: 0,
|
|
|
+ // high: Default::default(),
|
|
|
+ // low: Default::default(),
|
|
|
+ // sell: ap,
|
|
|
+ // buy: bp,
|
|
|
+ // last: Default::default(),
|
|
|
+ // volume: Default::default(),
|
|
|
+ // });
|
|
|
+ // }
|
|
|
+ // ref_price = [[bid_price, ask_price]]
|
|
|
+ // self.ref_price = self.predictor.get_ref_price(&ref_tickers);
|
|
|
}
|
|
|
|
|
|
// 本地记录所有报单信息
|
|
|
@@ -1867,6 +1936,7 @@ pub fn run_strategy(core_arc: Arc<Mutex<Core>>) -> JoinHandle<()> {
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
+ tokio::time::sleep(Duration::from_secs(1)).await;
|
|
|
core.check_ready();
|
|
|
}
|
|
|
// 计算耗时并进行休眠
|