瀏覽代碼

k线基础数据添加完毕,可以计算MFI。

skyffire 1 年之前
父節點
當前提交
3dd622ad39

+ 5 - 5
exchanges/src/bybit_swap_rest.rs

@@ -88,12 +88,12 @@ impl BybitSwapRest {
         data
     }
     //查詢市場價格K線數據
-    pub async fn get_kline(&mut self, symbol: String) -> ResponseData {
+    pub async fn get_record(&mut self, symbol: String, interval: String, limit: String) -> ResponseData {
         let params = serde_json::json!({
-               "category":"linear",
-                "symbol":symbol,
-                "interval":"1",
-                "limit":"200"
+               "category": "linear",
+                "symbol": symbol,
+                "interval": interval,
+                "limit": limit
          });
         let data = self.request("GET".to_string(),
                                 "/v5".to_string(),

+ 1 - 1
exchanges/tests/bybit_swap_test.rs

@@ -223,7 +223,7 @@ async fn rest_get_kline_test() {
     global::log_utils::init_log_with_trace();
 
     let mut ret = get_rest();
-    let req_data = ret.get_kline("DOGEUSDT".to_string()).await;
+    let req_data = ret.get_record("DOGEUSDT".to_string(), "1".to_string(), "5".to_string()).await;
     println!("Bybit--查詢市場價格K線數據--{:?}", req_data);
 }
 

+ 5 - 1
standard/src/binance_swap.rs

@@ -13,7 +13,7 @@ use tokio::spawn;
 use tokio::sync::mpsc::Sender;
 use tokio::time::Instant;
 use tracing::{error, info};
-use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, utils, PositionModeEnum};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, utils, PositionModeEnum, Record};
 use exchanges::binance_swap_rest::BinanceSwapRest;
 use global::trace_stack::TraceStack;
 
@@ -192,6 +192,10 @@ impl Platform for BinanceSwap {
         }
     }
 
+    async fn get_record(&mut self, _interval: String) -> Result<Vec<Record>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "binance_usdt_swap:该交易所方法未实现".to_string()))
+    }
+
     async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
         let symbol_format = utils::format_symbol(symbol.clone(), "");
         let res_data = self.request.get_book_ticker(symbol_format).await;

+ 30 - 1
standard/src/bybit_swap.rs

@@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize};
 use tokio::time::Instant;
 use tracing::{error, info, trace};
 use exchanges::bybit_swap_rest::BybitSwapRest;
-use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, Record};
 use global::trace_stack::TraceStack;
 
 #[derive(Debug, Clone, Deserialize, Serialize)]
@@ -207,6 +207,35 @@ impl Platform for BybitSwap {
         }
     }
 
+    async fn get_record(&mut self, interval: String) -> Result<Vec<Record>, Error> {
+        let symbol = self.symbol_uppercase.clone();
+
+        let res_data = self.request.get_record(symbol, interval, "3".to_string()).await;
+
+        if res_data.code == 200 {
+            let mut records: Vec<Record> = vec![];
+
+            for record_value in res_data.data["list"].as_array().unwrap() {
+                let value_array = record_value.as_array().unwrap();
+
+                records.push(Record {
+                    time: Decimal::from_str(value_array[0].as_str().unwrap()).unwrap(),
+                    open: Decimal::from_str(value_array[1].as_str().unwrap()).unwrap(),
+                    high: Decimal::from_str(value_array[2].as_str().unwrap()).unwrap(),
+                    low: Decimal::from_str(value_array[3].as_str().unwrap()).unwrap(),
+                    close: Decimal::from_str(value_array[4].as_str().unwrap()).unwrap(),
+                    volume: Decimal::from_str(value_array[5].as_str().unwrap()).unwrap(),
+                    symbol: "".to_string(),
+                });
+            }
+
+            records.reverse();
+            Ok(records)
+        } else {
+            Err(Error::new(ErrorKind::Other, res_data.to_string()))
+        }
+    }
+
     async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
         let symbol_upper = symbol.replace("_", "").to_uppercase();
         let res_data = self.request.get_tickers(symbol_upper.clone()).await;

+ 5 - 1
standard/src/coinex_swap.rs

@@ -12,7 +12,7 @@ use tokio::spawn;
 use tokio::time::Instant;
 use tracing::{error, info, trace};
 use exchanges::coinex_swap_rest::CoinexSwapRest;
-use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, utils};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, utils, Record};
 use global::trace_stack::TraceStack;
 use crate::utils::get_tick_size;
 
@@ -199,6 +199,10 @@ impl Platform for CoinexSwap {
         }
     }
 
+    async fn get_record(&mut self, _interval: String) -> Result<Vec<Record>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "coinex_usdt_swap:该交易所方法未实现".to_string()))
+    }
+
     async fn get_ticker_symbol(&mut self, symbol_param: String) -> Result<Ticker, Error> {
         let symbol: String = symbol_param.replace("_", "").to_uppercase();
         let res_data = self.request.get_ticker(symbol.clone()).await;

+ 5 - 1
standard/src/gate_swap.rs

@@ -11,7 +11,7 @@ use serde_json::{json, Value};
 use tokio::spawn;
 use tokio::time::Instant;
 use tracing::{error, info};
-use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum};
+use crate::{Platform, ExchangeEnum, Account, Position, Ticker, Market, Order, OrderCommand, PositionModeEnum, Record};
 use exchanges::gate_swap_rest::GateSwapRest;
 use global::trace_stack::TraceStack;
 
@@ -182,6 +182,10 @@ impl Platform for GateSwap {
         }
     }
 
+    async fn get_record(&mut self, _interval: String) -> Result<Vec<Record>, Error> {
+        Err(Error::new(ErrorKind::NotFound, "gate_swap:该交易所方法未实现".to_string()))
+    }
+
     async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error> {
         let symbol_upper = symbol.to_uppercase();
         let symbol_array: Vec<&str> = symbol_upper.split("_").collect();

+ 2 - 0
standard/src/lib.rs

@@ -639,6 +639,8 @@ pub trait Platform {
     async fn get_positions(&mut self) -> Result<Vec<Position>, Error>;
     // 获取市场行情
     async fn get_ticker(&mut self) -> Result<Ticker, Error>;
+    // 获取市场行情
+    async fn get_record(&mut self, interval: String) -> Result<Vec<Record>, Error>;
     // 获取市场行情自定义交易对
     async fn get_ticker_symbol(&mut self, symbol: String) -> Result<Ticker, Error>;
     // 查询所有的市场信息

+ 15 - 1
strategy/src/avellaneda_stoikov.rs

@@ -17,6 +17,7 @@ pub struct AvellanedaStoikov {
     pub trade_long_vec: FixedTimeRangeDeque<Trade>,                             // 交易队列
     pub trade_short_vec: FixedTimeRangeDeque<Trade>,                            // 交易队列
     pub spread_vec: FixedTimeRangeDeque<Decimal>,
+    pub record_vec: FixedTimeRangeDeque<Record>,                                // 蜡烛队列
 
     pub mid_price: Decimal,                                                     // 中间价
     pub ask_price: Decimal,                                                     // 卖一价
@@ -54,6 +55,7 @@ pub struct AvellanedaStoikov {
 impl AvellanedaStoikov {
     // 时间窗口大小(微秒)
     const MAX_TIME_RANGE_MICROS: i64 = 3 * 60_000_000;
+    const RECORD_RANGE_MICROS: i64 = 4 * 60_000_000;
     const TRADE_LONG_RANGE_MICROS: i64 = 3 * 60_000_000;
     const TRADE_SHORT_RANGE_MICROS: i64 = 20_000_000;
     // const ONE_MILLION: Decimal = dec!(1_000_000);
@@ -67,6 +69,7 @@ impl AvellanedaStoikov {
             spread_vec: FixedTimeRangeDeque::new(Self::MAX_TIME_RANGE_MICROS),
             trade_long_vec: FixedTimeRangeDeque::new(Self::TRADE_LONG_RANGE_MICROS),
             trade_short_vec: FixedTimeRangeDeque::new(Self::TRADE_SHORT_RANGE_MICROS),
+            record_vec: FixedTimeRangeDeque::new(Self::RECORD_RANGE_MICROS),
 
             mid_price: Default::default(),
             ask_price: Default::default(),
@@ -174,7 +177,18 @@ impl AvellanedaStoikov {
     pub async fn on_ticker(&mut self, _ticker: &Ticker) {}
 
     pub async fn on_record(&mut self, record: &Record) {
-        info!(?record);
+        // 添加新蜡烛
+        if self.record_vec.len() == 0 {
+            self.record_vec.push_back(record.clone());
+        } else {
+            let last_record = self.record_vec.deque.back_mut().unwrap();
+
+            if last_record.time == record.time {
+                *last_record = record.clone();
+            } else if last_record.time < record.time {
+                self.record_vec.push_back(record.clone());
+            }
+        }
     }
 
     pub async fn update_inventory(&mut self, inventory: &Decimal, min_amount_value: &Decimal) {

+ 9 - 2
strategy/src/bybit_usdt_swap.rs

@@ -35,8 +35,15 @@ pub(crate) async fn reference_bybit_swap_run(is_shutdown_arc: Arc<AtomicBool>,
 
         // 读取数据
         let core_arc_clone = Arc::clone(&core_arc);
-        let rest = core_arc_clone.lock().await.platform_rest.clone_box();
+        let mut rest = core_arc_clone.lock().await.platform_rest.clone_box();
         let multiplier = rest.get_self_market().multiplier;
+        let mut records = rest.get_record("1".to_string()).await.unwrap();
+        for record in records.iter_mut() {
+            let core_arc_clone = core_arc.clone();
+
+            on_record(core_arc_clone, record).await
+        }
+
         let depth_asks = Arc::new(Mutex::new(Vec::new()));
         let depth_bids = Arc::new(Mutex::new(Vec::new()));
 
@@ -179,7 +186,7 @@ async fn on_public_data(core_arc: Arc<Mutex<Core>>, mul: &Decimal, response: &Re
             for record in records.iter_mut() {
                 let core_arc_clone = core_arc.clone();
 
-                on_record(core_arc_clone, &mut trace_stack, record).await
+                on_record(core_arc_clone, record).await
             }
         },
         _ => {

+ 1 - 1
strategy/src/core.rs

@@ -616,7 +616,7 @@ impl Core {
         self.avellaneda_stoikov.on_ticker(ticker).await;
     }
 
-    pub async fn on_record(&mut self, record: &Record, _trace_stack: &mut TraceStack) {
+    pub async fn on_record(&mut self, record: &Record) {
         self.avellaneda_stoikov.on_record(record).await;
     }
 

+ 2 - 3
strategy/src/exchange_disguise.rs

@@ -144,11 +144,10 @@ pub async fn on_ticker(core_arc: Arc<Mutex<Core>>, trace_stack: &mut TraceStack,
     core.on_ticker(ticker, trace_stack).await;
 }
 
-pub async fn on_record(core_arc: Arc<Mutex<Core>>, trace_stack: &mut TraceStack, record: &Record) {
+pub async fn on_record(core_arc: Arc<Mutex<Core>>, record: &Record) {
     let mut core = core_arc.lock().await;
-    trace_stack.on_after_unlock_core();
 
-    core.on_record(record, trace_stack).await;
+    core.on_record(record).await;
 }
 
 pub async fn on_order() {}