JiahengHe %!s(int64=2) %!d(string=hai) anos
pai
achega
b76fba6131
Modificáronse 1 ficheiros con 134 adicións e 32 borrados
  1. 134 32
      strategy/src/quant.rs

+ 134 - 32
strategy/src/quant.rs

@@ -2,13 +2,17 @@ use std::collections::{BTreeMap, HashMap};
 use std::ops::Div;
 use std::str::FromStr;
 use std::thread;
+use std::thread::{sleep};
 use std::time::Duration;
 use chrono::{Timelike, Utc};
 use rust_decimal::Decimal;
 use rust_decimal_macros::dec;
 use global::public_params::{ASK_PRICE_INDEX, BID_PRICE_INDEX, LENGTH};
-use standard::{SpecialDepth, SpecialTicker, Ticker};
-use crate::model::{OrderCommand, OrderInfo, Position, TraderMsg};
+use standard::{Market, Platform, Position, PositionModeEnum, SpecialDepth, SpecialTicker, Ticker};
+use standard::exchange::Exchange;
+use standard::exchange::ExchangeEnum::GateSwap;
+
+use crate::model::{LocalPosition, OrderCommand, OrderInfo, TraderMsg};
 use crate::params::Params;
 use crate::predictor::Predictor;
 use crate::strategy::Strategy;
@@ -44,9 +48,9 @@ pub struct Quant {
     // 本地币保证金
     pub local_coin: Decimal,
     // 仓位信息
-    pub local_position: Position,
+    pub local_position: LocalPosition,
     // 仓位信息-自订单
-    pub local_position_by_orders: Position,
+    pub local_position_by_orders: LocalPosition,
     //
     pub local_buy_amount: Decimal,
     pub local_sell_amount: Decimal,
@@ -81,6 +85,7 @@ pub struct Quant {
     pub trade_name: String,
     pub ready: i8,
     pub predictor: Predictor,
+    pub market: Market
 }
 
 struct MarketData{
@@ -95,7 +100,7 @@ impl Quant {
         let mut quant_obj = Quant {
            params: params.clone(),
            start_time: 0,
-           symbol,
+           symbol: symbol.clone(),
            base: pairs[0].to_string(),
            quote: pairs[1].to_string(),
            hold_coin: clip(params.hold_coin, dec!(0.0), dec!(10000.0)),
@@ -107,13 +112,13 @@ impl Quant {
            local_profit: Default::default(),
            local_cash: Default::default(),
            local_coin: Default::default(),
-           local_position: Position{
+           local_position: LocalPosition{
                long_pos: Default::default(),
                short_pos: Default::default(),
                long_avg: Default::default(),
                short_avg: Default::default(),
            },
-           local_position_by_orders: Position{
+           local_position_by_orders: LocalPosition{
                long_pos: Default::default(),
                short_pos: Default::default(),
                long_avg: Default::default(),
@@ -152,6 +157,20 @@ impl Quant {
                alpha: vec![],
                gamma: Default::default(),
                avg_spread_list: vec![],
+           },
+           market: Market{
+               symbol,
+               base_asset: "".to_string(),
+               quote_asset: "".to_string(),
+               tick_size: Default::default(),
+               amount_size: Default::default(),
+               price_precision: Default::default(),
+               amount_precision: Default::default(),
+               min_qty: Default::default(),
+               max_qty: Default::default(),
+               min_notional: Default::default(),
+               max_notional: Default::default(),
+               ct_val: Default::default(),
            }
         };
         for i in 0..=params.ref_exchange.len()-1 {
@@ -416,6 +435,18 @@ impl Quant {
         }
     }
 
+    pub fn update_equity(&mut self, data: Decimal){
+        /*
+            更新保证金信息
+            合约一直更新
+            现货只有当出现异常时更新
+        */
+        if self.exchange.contains("spot"){
+            return;
+        }
+        self.local_cash = data * self.used_pct
+    }
+
     // 检测初始数据是否齐全
     pub fn check_ready(&mut self){
         // 检查 ticker 行情
@@ -519,10 +550,48 @@ impl Quant {
         }
     }
 
-    pub fn update_position(&mut self, data: Position){
+    pub fn update_exit(&mut self, data: String){
+        // 底层触发停机
+        self.exit_msg = data;
+
+    }
+    pub fn stop(&mut self){
+        self.mode_signal = 80;
+        // 等strategy onExit 彻底执行完毕 进入沉默状态之后 再进入exit 否则可能导致多处同时操作订单
+        // 尽量减少大仓位直接take平
+        // TODO:发起停机 self.loop.create_task(self.exit(delay=10))
+    }
+
+    pub fn exit(self, delay: i8){
+        println!("预约退出操作 delay: {}", delay);
+        if delay > 0{
+            sleep(Duration::from_secs(delay as u64));
+        }
+        println!("开始退出操作");
+        println!("为避免api失效导致遗漏仓位 建议人工复查");
+        // TODO: 检查仓位 await self.rest.check_position(hold_coin=self.hold_coin)
+        // stop flag
+
+
+    }
+
+    pub fn update_position(&mut self, data: Vec<Position>){
+        if data.is_empty(){
+            return;
+        }
+        let mut  position = LocalPosition::new();
+        for pos in data {
+            if pos.position_mode == PositionModeEnum::Long {
+                position.long_pos = pos.amount;
+                position.long_avg = pos.price;
+            } else if pos.position_mode == PositionModeEnum::Short {
+                position.short_pos = pos.amount;
+                position.short_avg = pos.price;
+            }
+        }
         // 更新仓位信息
-        if data != self.local_position {
-            self.local_position = data;
+        if position != self.local_position {
+            self.local_position = position;
             println!("更新本地仓位:{:?}", self.local_position);
         }
     }
@@ -647,39 +716,64 @@ impl Quant {
         return market;
     }
 
-    pub fn before_trade(&mut self){
+    pub async fn get_exchange_info(&mut self, platform: &Box<dyn Platform + Send + Sync>){
+        match platform.get_market().await {
+            Ok(val)=> {
+                self.market = val
+            },
+            Err(e) => {
+                println!("获取市场信息错误: {:?}", e);
+            }
+        }
+    }
+
+    pub async fn get_equity(&mut self, platform: &Box<dyn Platform + Send + Sync>){
+        match platform.get_account().await {
+            Ok(val)=> {
+                self.update_equity(val.balance);
+            },
+            Err(e) => {
+                println!("获取账户信息错误: {:?}", e);
+            }
+        }
+    }
+
+    pub async fn before_trade(&mut self){
         // 启动ws
         // 启动交易
         //TODO: 启动交易盘
-        // 启动交易盘 self.loop.create_task(self.ws.run(is_auth=1, sub_trade=_sub_trade, sub_fast=0))
+        let mut exchange_params = BTreeMap::new();
+        exchange_params.insert("access_key".to_string(), "your_access_key".to_string());
+        exchange_params.insert("access_key".to_string(), "your_secret_key".to_string());
+        let platform:Box<dyn Platform+Send+Sync> = Exchange::new(GateSwap, self.symbol.clone(), false, exchange_params);
+
         for i in &self.ref_name{
             // TODO: 启动参考ws 参考盘口使用fast行情性能消耗更大 使用普通行情可以节省性能
             // self.loop.create_task(self.ws_ref[i].run(is_auth=0, sub_trade=0, sub_fast=_sub_fast))
         }
-        thread::sleep(Duration::from_secs(1));
-        // TODO:买入平台币操作 await self.rest.buy_token()
-        // TODO: 清空挂单和仓位 await self.rest.check_position(hold_coin=self.hold_coin)
-        // TODO: 获取市场信息 await self.rest.before_trade()
-        // TODO: 获取价格信息 ticker = await self.rest.get_ticker()
-        let ticker = SpecialTicker{
-            sell: Default::default(),
-            buy: Default::default(),
-            mid_price: Default::default(),
-        };
-        let mp = ticker.mid_price;
-        // TODO:获取账户信息 await self.rest.get_equity()
-        // TODO:初始资金 start_cash = self.rest.cash_value * self.used_pct  start_coin = self.rest.coin_value * self.used_pct
-        let start_cash = Decimal::ZERO;
-        let start_coin = Decimal::ZERO;
+        sleep(Duration::from_secs(1));
+        // 买入平台币操作 await self.rest.buy_token()
+        // 获取市场信息
+        self.get_exchange_info(&platform).await;
+        // 获取价格信息
+        let ticker = platform.get_ticker().await.expect("获取价格信息异常!");
+        let mp = (ticker.buy + ticker.sell) / Decimal::TWO;
+        // 获取账户信息
+        self.get_equity(&platform).await;
+        // 初始资金
+        let start_cash = self.local_cash.clone();
+        let start_coin = self.local_cash.clone();
         if start_cash.is_zero() && start_coin.is_zero(){
             self.exit_msg = format!("{}{}{}{}","初始为零 cash: ", start_cash, " coin: ", start_coin);
             // TODO: 停止程序 self.stop()
             return;
         }
-        // self.logger.info(f"初始cash: {start_cash} 初始coin: {start_coin}")
+        println!("初始cash: {start_cash} 初始coin: {start_coin}");
         // 初始化策略基础信息
         if mp <= dec!(0){
             self.exit_msg = format!("{}{}","初始价格获取错误: ", mp);
+            // TODO: 停止程序 self.stop()
+            return;
         } else {
             println!("初始价格为 {}", mp);
         }
@@ -690,10 +784,16 @@ impl Quant {
         self.strategy.max_equity = self.strategy.start_equity.clone();
         self.strategy.equity = self.strategy.start_equity.clone();
         self.strategy.total_amount = self.strategy.equity * self.strategy.lever_rate / self.strategy.mp;
-        // TODO: 获取数量精度  self.strategy.stepSize = self.rest.stepSize if self.rest.stepSize < 1.0 else int(self.rest.stepSize)
-        self.strategy.step_size = Decimal::ZERO;
-        // TODO: 获取价格精度 self.rest.tickSize if self.rest.tickSize < 1.0 else int(self.rest.tickSize)
-        self.strategy.tick_size = Decimal::ZERO;
+        // 获取数量精度
+        self.strategy.step_size = self.market.amount_size.clone();
+        if self.strategy.step_size < Decimal::ONE{
+            self.strategy.step_size = self.strategy.step_size.trunc();
+        }
+        // 获取价格精度 self.rest.tickSize if self.rest.tickSize < 1.0 else int(self.rest.tickSize)
+        self.strategy.tick_size = self.market.tick_size.clone();
+        if self.strategy.tick_size < Decimal::ONE{
+            self.strategy.tick_size = self.strategy.tick_size.trunc();
+        }
         if self.strategy.step_size.is_zero() || self.strategy.tick_size.is_zero(){
             self.exit_msg = format!("{}{}{}{}","交易精度未正常获取 step_size: ", self.strategy.step_size, " tick_size:", self.strategy.tick_size);
             // TODO: 停止程序 self.stop()
@@ -795,4 +895,6 @@ mod tests {
         println!("long_one_hand_amount:{:?}, short_one_hand_amount: {:?}", long_one_hand_amount, short_one_hand_amount);
         println!("{:?},{:?},{:?},{:?},{:?}", short_one_hand_value, mp, step_size, (short_one_hand_value/mp/step_size), ((short_one_hand_value/mp)/step_size).floor())
     }
+
+
 }