mod utils; const EXCHANGE_NAME: &str = "okx"; // V5 API #[cfg(test)] mod trade { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_message::TradeSide; use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_trade, round}; #[test] fn spot() { let raw_msg = r#"{"arg":{"channel":"trades","instId":"BTC-USDT"},"data":[{"instId":"BTC-USDT","tradeId":"314161276","px":"43474.1","sz":"0.00373695","side":"buy","ts":"1646311839593"}]}"#; let trades = &parse_trade(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap(); assert_eq!(trades.len(), 1); let trade = &trades[0]; crate::utils::check_trade_fields( EXCHANGE_NAME, MarketType::Spot, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap(), trade, raw_msg, ); assert_eq!( 1646311839593, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!(trade.timestamp, 1646311839593); assert_eq!(trade.quantity_base, 0.00373695); assert_eq!(trade.price, 43474.1); assert_eq!(trade.quantity_contract, None); assert_eq!(trade.side, TradeSide::Buy); } #[test] fn linear_future() { let raw_msg = r#"{"arg":{"channel":"trades","instId":"BTC-USDT-220325"},"data":[{"instId":"BTC-USDT-220325","tradeId":"17400303","px":"43535.3","sz":"2","side":"sell","ts":"1646311972504"}]}"#; let trades = &parse_trade(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap(); assert_eq!(trades.len(), 1); let trade = &trades[0]; crate::utils::check_trade_fields( EXCHANGE_NAME, MarketType::LinearFuture, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap(), trade, raw_msg, ); assert_eq!( 1646311972504, extract_timestamp(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap().unwrap() ); assert_eq!(trade.timestamp, 1646311972504); assert_eq!(trade.price, 43535.3); assert_eq!(trade.quantity_contract, Some(2.0)); assert_eq!(trade.quantity_base, 2.0 * 0.01); assert_eq!(trade.quantity_quote, round(2.0 * 0.01 * 43535.3)); assert_eq!(trade.side, TradeSide::Sell); } #[test] fn linear_swap() { let raw_msg = r#"{"arg":{"channel":"trades","instId":"BTC-USDT-SWAP"},"data":[{"instId":"BTC-USDT-SWAP","tradeId":"219066264","px":"43568.8","sz":"7","side":"buy","ts":"1646312440645"}]}"#; let trades = &parse_trade(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(); assert_eq!(trades.len(), 1); let trade = &trades[0]; crate::utils::check_trade_fields( EXCHANGE_NAME, MarketType::LinearSwap, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(), trade, raw_msg, ); assert_eq!( 1646312440645, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!(trade.timestamp, 1646312440645); assert_eq!(trade.price, 43568.8); assert_eq!(trade.quantity_contract, Some(7.0)); assert_eq!(trade.quantity_base, 7.0 * 0.01); assert_eq!(trade.quantity_quote, round(7.0 * 0.01 * 43568.8)); assert_eq!(trade.side, TradeSide::Buy); } #[test] fn inverse_future() { let raw_msg = r#"{"arg":{"channel":"trades","instId":"BTC-USD-220325"},"data":[{"instId":"BTC-USD-220325","tradeId":"18928717","px":"43568.7","sz":"1","side":"sell","ts":"1646312543604"}]}"#; let trades = &parse_trade(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap(); assert_eq!(trades.len(), 1); let trade = &trades[0]; crate::utils::check_trade_fields( EXCHANGE_NAME, MarketType::InverseFuture, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap(), trade, raw_msg, ); assert_eq!( 1646312543604, extract_timestamp(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap().unwrap() ); assert_eq!(trade.timestamp, 1646312543604); assert_eq!(trade.price, 43568.7); assert_eq!(trade.quantity_contract, Some(1.0)); assert_eq!(trade.quantity_quote, 100.0 * 1.0); assert_eq!(trade.quantity_base, 100.0 * 1.0 / 43568.7); assert_eq!(trade.side, TradeSide::Sell); } #[test] fn inverse_swap() { let raw_msg = r#"{"arg":{"channel":"trades","instId":"BTC-USD-SWAP"},"data":[{"instId":"BTC-USD-SWAP","tradeId":"173543957","px":"43574.9","sz":"1","side":"sell","ts":"1646312664791"}]}"#; let trades = &parse_trade(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap(); assert_eq!(trades.len(), 1); let trade = &trades[0]; crate::utils::check_trade_fields( EXCHANGE_NAME, MarketType::InverseSwap, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap(), trade, raw_msg, ); assert_eq!( 1646312664791, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!(trade.timestamp, 1646312664791); assert_eq!(trade.price, 43574.9); assert_eq!(trade.quantity_contract, Some(1.0)); assert_eq!(trade.quantity_quote, 100.0 * 1.0); assert_eq!(trade.quantity_base, 100.0 * 1.0 / 43574.9); assert_eq!(trade.side, TradeSide::Sell); } #[test] fn option() { let raw_msg = r#"{"arg":{"channel":"trades","instId":"BTC-USD-220304-32000-P"},"data":[{"instId":"BTC-USD-220304-32000-P","tradeId":"81","px":"0.001","sz":"85","side":"buy","ts":"1646138219181"}]}"#; let trades = &parse_trade(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap(); assert_eq!(trades.len(), 1); let trade = &trades[0]; crate::utils::check_trade_fields( EXCHANGE_NAME, MarketType::EuropeanOption, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap(), trade, raw_msg, ); assert_eq!( "BTC-USD-220304-32000-P", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!( 1646138219181, extract_timestamp(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap().unwrap() ); assert_eq!(trade.timestamp, 1646138219181); assert_eq!(trade.price, 0.001); assert_eq!(trade.quantity_contract, Some(85.0)); assert_eq!(trade.quantity_base, 85.0); assert_eq!(trade.quantity_quote, 85.0 * 0.001); assert_eq!(trade.side, TradeSide::Buy); } } #[cfg(test)] mod funding_rate { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_funding_rate}; #[test] fn inverse_swap() { let raw_msg = r#"{"arg":{"channel":"funding-rate","instId":"BTC-USD-SWAP"},"data":[{"fundingRate":"0.0000734174532791","fundingTime":"1646323200000","instId":"BTC-USD-SWAP","instType":"SWAP","nextFundingRate":"0.0001163723201487"}]}"#; let received_at = 1646323212345; let funding_rates = &parse_funding_rate(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, Some(received_at)) .unwrap(); assert_eq!(funding_rates.len(), 1); for rate in funding_rates.iter() { crate::utils::check_funding_rate_fields( EXCHANGE_NAME, MarketType::InverseSwap, rate, raw_msg, ); } assert_eq!( "BTC-USD-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!(funding_rates[0].pair, "BTC/USD".to_string()); assert_eq!(funding_rates[0].funding_rate, 0.0000734174532791); assert_eq!(funding_rates[0].estimated_rate, Some(0.0001163723201487)); assert_eq!(funding_rates[0].funding_time, 1646323200000); assert_eq!(funding_rates[0].timestamp, received_at); } #[test] fn linear_swap() { let raw_msg = r#"{"arg":{"channel":"funding-rate","instId":"BTC-USDT-SWAP"},"data":[{"fundingRate":"0.0001534702159002","fundingTime":"1646323200000","instId":"BTC-USDT-SWAP","instType":"SWAP","nextFundingRate":"0.0001542145319804"}]}"#; let received_at = 1646323212345; let funding_rates = &parse_funding_rate(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, Some(received_at)) .unwrap(); assert_eq!(funding_rates.len(), 1); for rate in funding_rates.iter() { crate::utils::check_funding_rate_fields( EXCHANGE_NAME, MarketType::InverseSwap, rate, raw_msg, ); } assert_eq!( "BTC-USDT-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!(funding_rates[0].pair, "BTC/USDT".to_string()); assert_eq!(funding_rates[0].funding_rate, 0.0001534702159002); assert_eq!(funding_rates[0].estimated_rate, Some(0.0001542145319804)); assert_eq!(funding_rates[0].funding_time, 1646323200000); assert_eq!(funding_rates[0].timestamp, received_at); } } #[cfg(test)] mod l2_event { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_l2, round}; use crypto_msg_type::MessageType; #[test] fn spot_snapshot() { let raw_msg = r#"{"arg":{"channel":"books-l2-tbt","instId":"BTC-USDT"},"action":"snapshot","data":[{"asks":[["43666.1","1.09431286","0","15"],["43666.3","0.01","0","1"],["43668.1","0.00102036","0","1"]],"bids":[["43666","0.00278174","0","5"],["43664","0.00245053","0","2"],["43662","0.00245065","0","2"]],"ts":"1646313944551","checksum":144433427}]}"#; let orderbook = &parse_l2(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 3); assert_eq!(orderbook.bids.len(), 3); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::Spot, MessageType::L2Event, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1646313944551, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1646313944551); assert_eq!(orderbook.bids[0].price, 43666.0); assert_eq!(orderbook.bids[0].quantity_base, 0.00278174); assert_eq!(orderbook.bids[0].quantity_quote, 43666.0 * 0.00278174); assert_eq!(orderbook.asks[0].price, 43666.1); assert_eq!(orderbook.asks[0].quantity_base, 1.09431286); assert_eq!(orderbook.asks[0].quantity_quote, 1.09431286 * 43666.1); } #[test] fn spot_update() { let raw_msg = r#"{"arg":{"channel":"books-l2-tbt","instId":"BTC-USDT"},"action":"update","data":[{"asks":[["43736.2","0.1358","0","2"]],"bids":[["43675.6","0.05","0","1"]],"ts":"1646314295200","checksum":796530682}]}"#; let orderbook = &parse_l2(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 1); assert_eq!(orderbook.bids.len(), 1); assert!(!orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::Spot, MessageType::L2Event, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1646314295200, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1646314295200); assert_eq!(orderbook.bids[0].price, 43675.6); assert_eq!(orderbook.bids[0].quantity_base, 0.05); assert_eq!(orderbook.bids[0].quantity_quote, 43675.6 * 0.05); assert_eq!(orderbook.asks[0].price, 43736.2); assert_eq!(orderbook.asks[0].quantity_base, 0.1358); assert_eq!(orderbook.asks[0].quantity_quote, round(43736.2 * 0.1358)); } #[test] fn linear_future_snapshot() { let raw_msg = r#"{"arg":{"channel":"books-l2-tbt","instId":"BTC-USDT-220325"},"action":"snapshot","data":[{"asks":[["43741.9","4","0","1"],["43743.4","1","0","1"],["43743.5","4","0","1"]],"bids":[["43741.8","2","0","1"],["43739.3","4","0","1"],["43738","34","0","1"]],"ts":"1646314548269","checksum":2127111983}]}"#; let orderbook = &parse_l2(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 3); assert_eq!(orderbook.bids.len(), 3); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::LinearFuture, MessageType::L2Event, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1646314548269, extract_timestamp(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1646314548269); assert_eq!(orderbook.asks[0].price, 43741.9); assert_eq!(orderbook.asks[0].quantity_contract, Some(4.0)); assert_eq!(orderbook.asks[0].quantity_base, 4.0 * 0.01); assert_eq!(orderbook.asks[0].quantity_quote, round(4.0 * 0.01 * 43741.9)); assert_eq!(orderbook.bids[0].price, 43741.8); assert_eq!(orderbook.bids[0].quantity_contract, Some(2.0)); assert_eq!(orderbook.bids[0].quantity_base, 2.0 * 0.01); assert_eq!(orderbook.bids[0].quantity_quote, round(2.0 * 0.01 * 43741.8)); } #[test] fn inverse_swap_snapshot() { let raw_msg = r#"{"arg":{"channel":"books-l2-tbt","instId":"BTC-USD-SWAP"},"action":"snapshot","data":[{"asks":[["43726.4","145","0","5"],["43730.5","10","0","1"],["43733.1","45","0","1"]],"bids":[["43726.3","131","0","1"],["43726","10","0","1"],["43722","16","0","1"]],"ts":"1646314888087","checksum":-1817371130}]}"#; let orderbook = &parse_l2(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 3); assert_eq!(orderbook.bids.len(), 3); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::InverseSwap, MessageType::L2Event, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1646314888087, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1646314888087); assert_eq!(orderbook.asks[0].price, 43726.4); assert_eq!(orderbook.asks[0].quantity_contract, Some(145.0)); assert_eq!(orderbook.asks[0].quantity_quote, 100.0 * 145.0); assert_eq!(orderbook.asks[0].quantity_base, 100.0 * 145.0 / 43726.4); assert_eq!(orderbook.bids[0].price, 43726.3); assert_eq!(orderbook.bids[0].quantity_contract, Some(131.0)); assert_eq!(orderbook.bids[0].quantity_quote, 100.0 * 131.0); assert_eq!(orderbook.bids[0].quantity_base, 100.0 * 131.0 / 43726.3); } #[test] fn option_snapshot() { let raw_msg = r#"{"arg":{"channel":"books-l2-tbt","instId":"BTC-USD-220304-32000-P"},"action":"snapshot","data":[{"asks":[["0.0005","305","0","1"],["0.001","550","0","2"]],"bids":[],"ts":"1646315100798","checksum":971343753}]}"#; let orderbook = &parse_l2(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 2); assert_eq!(orderbook.bids.len(), 0); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::EuropeanOption, MessageType::L2Event, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1646315100798, extract_timestamp(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1646315100798); assert_eq!(orderbook.asks[0].price, 0.0005); assert_eq!(orderbook.asks[0].quantity_contract, Some(305.0)); assert_eq!(orderbook.asks[0].quantity_base, 305.0); assert_eq!(orderbook.asks[0].quantity_quote, 305.0 * 0.0005); } } #[cfg(test)] mod l2_topk { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_l2_topk, round}; use crypto_msg_type::MessageType; #[test] fn spot() { let raw_msg = r#"{"arg":{"channel":"books5","instId":"BTC-USDT"},"data":[{"asks":[["30221.8","0.00439","0","2"],["30223.5","1.12","0","1"],["30223.7","1.16000647","0","3"],["30224.6","1.22","0","1"],["30225.6","1.64553107","0","2"]],"bids":[["30221.7","0.30608367","0","6"],["30220.9","0.01321829","0","1"],["30219.6","1.06226719","0","2"],["30219.5","0.0130546","0","1"],["30219.4","0.41","0","2"]],"instId":"BTC-USDT","ts":"1652671418459"}]}"#; let orderbook = &parse_l2_topk(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 5); assert_eq!(orderbook.bids.len(), 5); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::Spot, MessageType::L2TopK, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1652671418459, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1652671418459); assert_eq!(orderbook.seq_id, None); assert_eq!(orderbook.prev_seq_id, None); assert_eq!(orderbook.bids[0].price, 30221.7); assert_eq!(orderbook.bids[0].quantity_base, 0.30608367); assert_eq!(orderbook.bids[0].quantity_quote, round(30221.7 * 0.30608367)); assert_eq!(orderbook.bids[0].quantity_contract, None); assert_eq!(orderbook.bids[4].price, 30219.4); assert_eq!(orderbook.bids[4].quantity_base, 0.41); assert_eq!(orderbook.bids[4].quantity_quote, 30219.4 * 0.41); assert_eq!(orderbook.bids[4].quantity_contract, None); assert_eq!(orderbook.asks[0].price, 30221.8); assert_eq!(orderbook.asks[0].quantity_base, 0.00439); assert_eq!(orderbook.asks[0].quantity_quote, 0.00439 * 30221.8); assert_eq!(orderbook.asks[0].quantity_contract, None); assert_eq!(orderbook.asks[4].price, 30225.6); assert_eq!(orderbook.asks[4].quantity_base, 1.64553107); assert_eq!(orderbook.asks[4].quantity_quote, 1.64553107 * 30225.6); assert_eq!(orderbook.asks[4].quantity_contract, None); } #[test] fn spot_2() { let raw_msg = r#"{"table":"spot/depth5","data":[{"asks":[["0.9788","0.001","1"],["0.9789","0.944259","7"],["0.979","1.956785","1"],["0.9792","0.9401","1"],["0.98","31.459918","8"]],"bids":[["0.9768","0.605755","1"],["0.976","1.0532","1"],["0.9757","0.002","1"],["0.9752","0.720555","1"],["0.9748","0.001","1"]],"instrument_id":"BETH-ETH","timestamp":"2022-02-25T00:00:01.032Z"}]}"#; let orderbook = &parse_l2_topk(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 5); assert_eq!(orderbook.bids.len(), 5); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::Spot, MessageType::L2TopK, "BETH/ETH".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!("BETH-ETH", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()); assert_eq!( 1645747201032, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1645747201032); assert_eq!(orderbook.seq_id, None); assert_eq!(orderbook.prev_seq_id, None); assert_eq!(orderbook.bids[0].price, 0.9768); assert_eq!(orderbook.bids[0].quantity_base, 0.605755); assert_eq!(orderbook.bids[0].quantity_quote, 0.9768 * 0.605755); assert_eq!(orderbook.bids[0].quantity_contract, None); assert_eq!(orderbook.bids[4].price, 0.9748); assert_eq!(orderbook.bids[4].quantity_base, 0.001); assert_eq!(orderbook.bids[4].quantity_quote, round(0.9748 * 0.001)); assert_eq!(orderbook.bids[4].quantity_contract, None); assert_eq!(orderbook.asks[0].price, 0.9788); assert_eq!(orderbook.asks[0].quantity_base, 0.001); assert_eq!(orderbook.asks[0].quantity_quote, 0.001 * 0.9788); assert_eq!(orderbook.asks[0].quantity_contract, None); assert_eq!(orderbook.asks[4].price, 0.98); assert_eq!(orderbook.asks[4].quantity_base, 31.459918); assert_eq!(orderbook.asks[4].quantity_quote, round(31.459918 * 0.98)); assert_eq!(orderbook.asks[4].quantity_contract, None); } #[test] fn inverse_future() { let raw_msg = r#"{"arg":{"channel":"books5","instId":"BTC-USD-220624"},"data":[{"asks":[["31835.7","690","0","2"],["31841.2","5","0","1"],["31841.5","148","0","1"],["31841.8","5","0","1"],["31843.4","10","0","1"]],"bids":[["31835.6","6","0","2"],["31834","1","0","1"],["31833.2","23","0","1"],["31833.1","403","0","2"],["31832.9","5","0","1"]],"instId":"BTC-USD-220624","ts":"1653997473120"}]}"#; let orderbook = &parse_l2_topk(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 5); assert_eq!(orderbook.bids.len(), 5); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::InverseFuture, MessageType::L2TopK, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1653997473120, extract_timestamp(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1653997473120); assert_eq!(orderbook.seq_id, None); assert_eq!(orderbook.prev_seq_id, None); assert_eq!(orderbook.asks[0].price, 31835.7); assert_eq!(orderbook.asks[0].quantity_quote, 100.0 * 690.0); assert_eq!(orderbook.asks[0].quantity_base, 100.0 * 690.0 / 31835.7); assert_eq!(orderbook.asks[0].quantity_contract, Some(690.0)); assert_eq!(orderbook.asks[4].price, 31843.4); assert_eq!(orderbook.asks[4].quantity_quote, 100.0 * 10.0); assert_eq!(orderbook.asks[4].quantity_base, 100.0 * 10.0 / 31843.4); assert_eq!(orderbook.asks[4].quantity_contract, Some(10.0)); assert_eq!(orderbook.bids[0].price, 31835.6); assert_eq!(orderbook.bids[0].quantity_quote, 100.0 * 6.0); assert_eq!(orderbook.bids[0].quantity_base, 100.0 * 6.0 / 31835.6); assert_eq!(orderbook.bids[0].quantity_contract, Some(6.0)); assert_eq!(orderbook.bids[4].price, 31832.9); assert_eq!(orderbook.bids[4].quantity_quote, 100.0 * 5.0); assert_eq!(orderbook.bids[4].quantity_base, 100.0 * 5.0 / 31832.9); assert_eq!(orderbook.bids[4].quantity_contract, Some(5.0)); } #[test] fn linear_future() { let raw_msg = r#"{"arg":{"channel":"books5","instId":"BTC-USDT-220624"},"data":[{"asks":[["30351.5","18","0","2"],["30355.2","6","0","1"],["30355.3","30","0","2"],["30356.5","1","0","1"],["30358","1","0","1"]],"bids":[["30346.1","1","0","1"],["30344.5","8","0","1"],["30343.6","1","0","1"],["30343.4","1","0","1"],["30340.6","45","0","1"]],"instId":"BTC-USDT-220624","ts":"1652672165391"}]}"#; let orderbook = &parse_l2_topk(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 5); assert_eq!(orderbook.bids.len(), 5); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::LinearFuture, MessageType::L2TopK, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1652672165391, extract_timestamp(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1652672165391); assert_eq!(orderbook.seq_id, None); assert_eq!(orderbook.prev_seq_id, None); assert_eq!(orderbook.asks[0].price, 30351.5); assert_eq!(orderbook.asks[0].quantity_base, 18.0 * 0.01); assert_eq!(orderbook.asks[0].quantity_quote, round(18.0 * 0.01 * 30351.5)); assert_eq!(orderbook.asks[0].quantity_contract, Some(18.0)); assert_eq!(orderbook.asks[4].price, 30358.0); assert_eq!(orderbook.asks[4].quantity_base, 1.0 * 0.01); assert_eq!(orderbook.asks[4].quantity_quote, 1.0 * 0.01 * 30358.0); assert_eq!(orderbook.asks[4].quantity_contract, Some(1.0)); assert_eq!(orderbook.bids[0].price, 30346.1); assert_eq!(orderbook.bids[0].quantity_base, 1.0 * 0.01); assert_eq!(orderbook.bids[0].quantity_quote, 1.0 * 0.01 * 30346.1); assert_eq!(orderbook.bids[0].quantity_contract, Some(1.0)); assert_eq!(orderbook.bids[4].price, 30340.6); assert_eq!(orderbook.bids[4].quantity_base, 45.0 * 0.01); assert_eq!(orderbook.bids[4].quantity_quote, 45.0 * 0.01 * 30340.6); assert_eq!(orderbook.bids[4].quantity_contract, Some(45.0)); } #[test] fn inverse_swap() { let raw_msg = r#"{"arg":{"channel":"books5","instId":"BTC-USD-SWAP"},"data":[{"asks":[["29502","350","0","19"],["29502.2","42","0","2"],["29502.3","62","0","1"],["29502.7","5","0","1"],["29505","3","0","1"]],"bids":[["29501.9","77","0","1"],["29500.7","194","0","1"],["29499.5","1","0","1"],["29496.6","2","0","1"],["29495.1","1","0","1"]],"instId":"BTC-USD-SWAP","ts":"1652686260965"}]}"#; let orderbook = &parse_l2_topk(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 5); assert_eq!(orderbook.bids.len(), 5); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::InverseSwap, MessageType::L2TopK, "BTC/USD".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1652686260965, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1652686260965); assert_eq!(orderbook.seq_id, None); assert_eq!(orderbook.prev_seq_id, None); assert_eq!(orderbook.asks[0].price, 29502.0); assert_eq!(orderbook.asks[0].quantity_quote, 100.0 * 350.0); assert_eq!(orderbook.asks[0].quantity_base, 100.0 * 350.0 / 29502.0); assert_eq!(orderbook.asks[0].quantity_contract, Some(350.0)); assert_eq!(orderbook.asks[4].price, 29505.0); assert_eq!(orderbook.asks[4].quantity_quote, 100.0 * 3.0); assert_eq!(orderbook.asks[4].quantity_base, 100.0 * 3.0 / 29505.0); assert_eq!(orderbook.asks[4].quantity_contract, Some(3.0)); assert_eq!(orderbook.bids[0].price, 29501.9); assert_eq!(orderbook.bids[0].quantity_quote, 100.0 * 77.0); assert_eq!(orderbook.bids[0].quantity_base, 100.0 * 77.0 / 29501.9); assert_eq!(orderbook.bids[0].quantity_contract, Some(77.0)); assert_eq!(orderbook.bids[4].price, 29495.1); assert_eq!(orderbook.bids[4].quantity_quote, 100.0 * 1.0); assert_eq!(orderbook.bids[4].quantity_base, 100.0 * 1.0 / 29495.1); assert_eq!(orderbook.bids[4].quantity_contract, Some(1.0)); } #[test] fn linear_swap() { let raw_msg = r#"{"arg":{"channel":"books5","instId":"BTC-USDT-SWAP"},"data":[{"asks":[["31806.6","159","0","6"],["31807.1","9","0","3"],["31807.5","32","0","1"],["31807.9","28","0","1"],["31808.3","1","0","1"]],"bids":[["31806.5","54","0","3"],["31806","1","0","1"],["31805.7","5","0","1"],["31805.6","4","0","1"],["31805","10","0","2"]],"instId":"BTC-USDT-SWAP","ts":"1653997254735"}]}"#; let orderbook = &parse_l2_topk(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap()[0]; assert_eq!(orderbook.asks.len(), 5); assert_eq!(orderbook.bids.len(), 5); assert!(orderbook.snapshot); crate::utils::check_orderbook_fields( EXCHANGE_NAME, MarketType::LinearSwap, MessageType::L2TopK, "BTC/USDT".to_string(), extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(), orderbook, raw_msg, ); assert_eq!( 1653997254735, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!(orderbook.timestamp, 1653997254735); assert_eq!(orderbook.seq_id, None); assert_eq!(orderbook.prev_seq_id, None); assert_eq!(orderbook.asks[0].price, 31806.6); assert_eq!(orderbook.asks[0].quantity_base, 159.0 * 0.01); assert_eq!(orderbook.asks[0].quantity_quote, 159.0 * 0.01 * 31806.6); assert_eq!(orderbook.asks[0].quantity_contract, Some(159.0)); assert_eq!(orderbook.asks[4].price, 31808.3); assert_eq!(orderbook.asks[4].quantity_base, 1.0 * 0.01); assert_eq!(orderbook.asks[4].quantity_quote, 1.0 * 0.01 * 31808.3); assert_eq!(orderbook.asks[4].quantity_contract, Some(1.0)); assert_eq!(orderbook.bids[0].price, 31806.5); assert_eq!(orderbook.bids[0].quantity_base, 54.0 * 0.01); assert_eq!(orderbook.bids[0].quantity_quote, round(54.0 * 0.01 * 31806.5)); assert_eq!(orderbook.bids[0].quantity_contract, Some(54.0)); assert_eq!(orderbook.bids[4].price, 31805.0); assert_eq!(orderbook.bids[4].quantity_base, 10.0 * 0.01); assert_eq!(orderbook.bids[4].quantity_quote, 10.0 * 0.01 * 31805.0); assert_eq!(orderbook.bids[4].quantity_contract, Some(10.0)); } #[test] fn option() { let raw_msg = r#"{"arg":{"channel":"books5","instId":"BTC-USD-220624-50000-C"},"data":[{"asks":[["0.001","606","0","2"],["0.0015","330","0","2"],["0.002","10","0","1"]],"bids":[],"instId":"BTC-USD-220624-50000-C","ts":"1654387553361"}]}"#; assert_eq!( 1654387553361, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-220624-50000-C", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap() ); } } #[cfg(test)] mod bbo { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_bbo}; use crypto_msg_type::MessageType; #[test] fn spot() { let raw_msg = r#"{"arg":{"channel":"bbo-tbt","instId":"BTC-USDT"},"data":[{"asks":[["31774.7","0.14368878","0","3"]],"bids":[["31774.6","0.3392211","0","3"]],"ts":"1654032991947"}]}"#; assert_eq!( 1654032991947, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!("BTC-USDT", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()); let bbo_msg = &parse_bbo(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap()[0]; assert_eq!(MessageType::BBO, bbo_msg.msg_type); assert_eq!("BTC-USDT", bbo_msg.symbol); assert_eq!(1654032991947, bbo_msg.timestamp); assert_eq!(None, bbo_msg.id); assert_eq!(31774.7, bbo_msg.ask_price); assert_eq!(0.14368878, bbo_msg.ask_quantity_base); assert_eq!(31774.7 * 0.14368878, bbo_msg.ask_quantity_quote); assert_eq!(None, bbo_msg.ask_quantity_contract); assert_eq!(31774.6, bbo_msg.bid_price); assert_eq!(0.3392211, bbo_msg.bid_quantity_base); assert_eq!(31774.6 * 0.3392211, bbo_msg.bid_quantity_quote); assert_eq!(None, bbo_msg.bid_quantity_contract); } #[test] fn inverse_future() { let raw_msg = r#"{"arg":{"channel":"bbo-tbt","instId":"BTC-USD-220624"},"data":[{"asks":[["31769.9","15","0","1"]],"bids":[["31769.8","38","0","6"]],"ts":"1654033096078"}]}"#; assert_eq!( 1654033096078, extract_timestamp(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-220624", extract_symbol(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg).unwrap() ); let bbo_msg = &parse_bbo(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg, None).unwrap()[0]; assert_eq!(MessageType::BBO, bbo_msg.msg_type); assert_eq!("BTC-USD-220624", bbo_msg.symbol); assert_eq!(1654033096078, bbo_msg.timestamp); assert_eq!(None, bbo_msg.id); assert_eq!(31769.9, bbo_msg.ask_price); assert_eq!(1500.0 / 31769.9, bbo_msg.ask_quantity_base); assert_eq!(1500.0, bbo_msg.ask_quantity_quote); assert_eq!(Some(15.0), bbo_msg.ask_quantity_contract); assert_eq!(31769.8, bbo_msg.bid_price); assert_eq!(3800.0 / 31769.8, bbo_msg.bid_quantity_base); assert_eq!(3800.0, bbo_msg.bid_quantity_quote); assert_eq!(Some(38.0), bbo_msg.bid_quantity_contract); } #[test] fn linear_future() { let raw_msg = r#"{"arg":{"channel":"bbo-tbt","instId":"BTC-USDT-220624"},"data":[{"asks":[["31854.6","4","0","1"]],"bids":[["31850.4","2","0","1"]],"ts":"1654033073837"}]}"#; assert_eq!( 1654033073837, extract_timestamp(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USDT-220624", extract_symbol(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg).unwrap() ); let bbo_msg = &parse_bbo(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg, None).unwrap()[0]; assert_eq!(MessageType::BBO, bbo_msg.msg_type); assert_eq!("BTC-USDT-220624", bbo_msg.symbol); assert_eq!(1654033073837, bbo_msg.timestamp); assert_eq!(None, bbo_msg.id); assert_eq!(31854.6, bbo_msg.ask_price); assert_eq!(0.04, bbo_msg.ask_quantity_base); assert_eq!(31854.6 * 0.04, bbo_msg.ask_quantity_quote); assert_eq!(Some(4.0), bbo_msg.ask_quantity_contract); assert_eq!(31850.4, bbo_msg.bid_price); assert_eq!(0.02, bbo_msg.bid_quantity_base); assert_eq!(31850.4 * 0.02, bbo_msg.bid_quantity_quote); assert_eq!(Some(2.0), bbo_msg.bid_quantity_contract); } #[test] fn inverse_swap() { let raw_msg = r#"{"arg":{"channel":"bbo-tbt","instId":"BTC-USD-SWAP"},"data":[{"asks":[["19920","3","0","1"]],"bids":[["19918.9","34","0","1"]],"ts":"1656633600013"}]}"#; assert_eq!( 1656633600013, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); let bbo_msg = &parse_bbo(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap()[0]; assert_eq!(MessageType::BBO, bbo_msg.msg_type); assert_eq!("BTC-USD-SWAP", bbo_msg.symbol); assert_eq!(1656633600013, bbo_msg.timestamp); assert_eq!(None, bbo_msg.id); assert_eq!(19920.0, bbo_msg.ask_price); assert_eq!(300.0 / 19920.0, bbo_msg.ask_quantity_base); assert_eq!(300.0, bbo_msg.ask_quantity_quote); assert_eq!(Some(3.0), bbo_msg.ask_quantity_contract); assert_eq!(19918.9, bbo_msg.bid_price); assert_eq!(3400.0 / 19918.9, bbo_msg.bid_quantity_base); assert_eq!(3400.0, bbo_msg.bid_quantity_quote); assert_eq!(Some(34.0), bbo_msg.bid_quantity_contract); } #[test] fn linear_swap() { let raw_msg = r#"{"arg":{"channel":"bbo-tbt","instId":"BTC-USDT-SWAP"},"data":[{"asks":[["20386.8","7","0","2"]],"bids":[["20386.7","50","0","5"]],"ts":"1656642503092"}]}"#; assert_eq!( 1656642503092, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USDT-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap() ); let bbo_msg = &parse_bbo(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap()[0]; assert_eq!(MessageType::BBO, bbo_msg.msg_type); assert_eq!("BTC-USDT-SWAP", bbo_msg.symbol); assert_eq!(1656642503092, bbo_msg.timestamp); assert_eq!(None, bbo_msg.id); assert_eq!(20386.8, bbo_msg.ask_price); assert_eq!(0.07, bbo_msg.ask_quantity_base); assert_eq!(20386.8 * 0.07, bbo_msg.ask_quantity_quote); assert_eq!(Some(7.0), bbo_msg.ask_quantity_contract); assert_eq!(20386.7, bbo_msg.bid_price); assert_eq!(0.5, bbo_msg.bid_quantity_base); assert_eq!(20386.7 * 0.5, bbo_msg.bid_quantity_quote); assert_eq!(Some(50.0), bbo_msg.bid_quantity_contract); } #[test] fn option() { let raw_msg = r#"{"arg":{"channel":"bbo-tbt","instId":"BTC-USD-220624-50000-C"},"data":[{"asks":[["0.0015","8","0","1"]],"bids":[],"ts":"1654033343415"}]}"#; assert_eq!( 1654033343415, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-220624-50000-C", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap() ); } } #[cfg(test)] mod candlestick { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_candlestick}; #[test] fn spot() { let raw_msg = r#"{"arg":{"channel":"candle1m","instId":"BTC-USDT"},"data":[["1654154580000","29930.7","29936.3","29930.7","29936.3","0.0111536","333.86246417"]]}"#; let received_at = 1654154580017; assert_eq!(None, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()); assert_eq!("BTC-USDT", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()); let arr = parse_candlestick(EXCHANGE_NAME, MarketType::Spot, raw_msg, Some(received_at)).unwrap(); assert_eq!(1, arr.len()); let candlestick_msg = &arr[0]; assert_eq!("BTC-USDT", candlestick_msg.symbol); assert_eq!(received_at, candlestick_msg.timestamp); assert_eq!("1m", candlestick_msg.period); assert_eq!(1654154580, candlestick_msg.begin_time); assert_eq!(29930.7, candlestick_msg.open); assert_eq!(29936.3, candlestick_msg.high); assert_eq!(29930.7, candlestick_msg.low); assert_eq!(29936.3, candlestick_msg.close); assert_eq!(0.0111536, candlestick_msg.volume); assert_eq!(Some(333.86246417), candlestick_msg.quote_volume); } #[test] fn inverse_future() { let raw_msg = r#"{"arg":{"channel":"candle1m","instId":"BTC-USD-220624"},"data":[["1654154580000","29901.6","29921.2","29901.6","29921.2","166","0.554"]]}"#; let received_at = 1654154580017; assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!( "BTC-USD-220624", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); let arr = parse_candlestick(EXCHANGE_NAME, MarketType::InverseFuture, raw_msg, Some(received_at)) .unwrap(); assert_eq!(1, arr.len()); let candlestick_msg = &arr[0]; assert_eq!("BTC-USD-220624", candlestick_msg.symbol); assert_eq!(received_at, candlestick_msg.timestamp); assert_eq!("1m", candlestick_msg.period); assert_eq!(1654154580, candlestick_msg.begin_time); assert_eq!(29901.6, candlestick_msg.open); assert_eq!(29921.2, candlestick_msg.high); assert_eq!(29901.6, candlestick_msg.low); assert_eq!(29921.2, candlestick_msg.close); assert_eq!(0.554, candlestick_msg.volume); assert_eq!(Some(16600.0), candlestick_msg.quote_volume); } #[test] fn linear_future() { let raw_msg = r#"{"arg":{"channel":"candle1m","instId":"BTC-USDT-220624"},"data":[["1654154520000","29963.4","29971.2","29958.8","29970.3","133","1.33"]]}"#; let received_at = 1654154520017; assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!( "BTC-USDT-220624", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); let arr = parse_candlestick(EXCHANGE_NAME, MarketType::LinearFuture, raw_msg, Some(received_at)) .unwrap(); assert_eq!(1, arr.len()); let candlestick_msg = &arr[0]; assert_eq!("BTC-USDT-220624", candlestick_msg.symbol); assert_eq!(received_at, candlestick_msg.timestamp); assert_eq!("1m", candlestick_msg.period); assert_eq!(1654154520, candlestick_msg.begin_time); assert_eq!(29963.4, candlestick_msg.open); assert_eq!(29971.2, candlestick_msg.high); assert_eq!(29958.8, candlestick_msg.low); assert_eq!(29970.3, candlestick_msg.close); assert_eq!(1.33, candlestick_msg.volume); assert_eq!(None, candlestick_msg.quote_volume); } #[test] fn inverse_swap() { let raw_msg = r#"{"arg":{"channel":"candle1m","instId":"BTC-USD-SWAP"},"data":[["1662716640000","20713.4","20721.5","20711.1","20721.5","1400","6.7561"]]}"#; let received_at = 1662716640017; assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); assert_eq!( "BTC-USD-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); let arr = parse_candlestick(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, Some(received_at)) .unwrap(); assert_eq!(1, arr.len()); let candlestick_msg = &arr[0]; assert_eq!("BTC-USD-SWAP", candlestick_msg.symbol); assert_eq!(received_at, candlestick_msg.timestamp); assert_eq!("1m", candlestick_msg.period); assert_eq!(1662716640, candlestick_msg.begin_time); assert_eq!(20713.4, candlestick_msg.open); assert_eq!(20721.5, candlestick_msg.high); assert_eq!(20711.1, candlestick_msg.low); assert_eq!(20721.5, candlestick_msg.close); assert_eq!(6.7561, candlestick_msg.volume); assert_eq!(Some(140000.0), candlestick_msg.quote_volume); } #[test] fn linear_swap() { let raw_msg = r#"{"arg":{"channel":"candle1m","instId":"BTC-USDT-SWAP"},"data":[["1662716640000","20702.4","20710","20702.3","20703.8","4070","40.7"]]}"#; let received_at = 1662716640017; assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap() ); assert_eq!( "BTC-USDT-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap() ); let arr = parse_candlestick(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, Some(received_at)) .unwrap(); assert_eq!(1, arr.len()); let candlestick_msg = &arr[0]; assert_eq!("BTC-USDT-SWAP", candlestick_msg.symbol); assert_eq!(received_at, candlestick_msg.timestamp); assert_eq!("1m", candlestick_msg.period); assert_eq!(1662716640, candlestick_msg.begin_time); assert_eq!(20702.4, candlestick_msg.open); assert_eq!(20710.0, candlestick_msg.high); assert_eq!(20702.3, candlestick_msg.low); assert_eq!(20703.8, candlestick_msg.close); assert_eq!(40.7, candlestick_msg.volume); assert_eq!(None, candlestick_msg.quote_volume); } #[test] fn option() { let raw_msg = r#"{"arg":{"channel":"candle1m","instId":"BTC-USD-220624-50000-C"},"data":[["1654155480000","0.0005","0.0005","0.0005","0.0005","0","0"]]}"#; assert_eq!( None, extract_timestamp(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap() ); assert_eq!( "BTC-USD-220624-50000-C", extract_symbol(EXCHANGE_NAME, MarketType::EuropeanOption, raw_msg).unwrap() ); } } #[cfg(test)] mod ticker { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp}; #[test] fn spot() { let raw_msg = r#"{"arg":{"channel":"tickers","instId":"BTC-USDT"},"data":[{"instType":"SPOT","instId":"BTC-USDT","last":"29934","lastSz":"0.00001468","askPx":"29934.1","askSz":"0.30918743","bidPx":"29934","bidSz":"0.05181315","open24h":"31588.3","high24h":"31899.8","low24h":"29318.7","sodUtc0":"29806.5","sodUtc8":"30747","volCcy24h":"302140058.01215828","vol24h":"9935.14546361","ts":"1654166073135"}]}"#; assert_eq!( 1654166073135, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!("BTC-USDT", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()); } #[test] fn inverse_future() { let raw_msg = r#"{"arg":{"channel":"tickers","instId":"BTC-USD-220624"},"data":[{"instType":"FUTURES","instId":"BTC-USD-220624","last":"29883.4","lastSz":"2","askPx":"29885.7","askSz":"3","bidPx":"29882","bidSz":"15","open24h":"31579.7","high24h":"31899.9","low24h":"29243.9","sodUtc0":"29748.4","sodUtc8":"30699.4","volCcy24h":"6540.5687","vol24h":"1985047","ts":"1654166101413"}]}"#; assert_eq!( 1654166101413, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-220624", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn linear_future() { let raw_msg = r#"{"arg":{"channel":"tickers","instId":"BTC-USDT-220624"},"data":[{"instType":"FUTURES","instId":"BTC-USDT-220624","last":"29973.6","lastSz":"1","askPx":"29973.6","askSz":"1","bidPx":"29973.5","bidSz":"34","open24h":"31666.9","high24h":"31978.1","low24h":"29336.7","sodUtc0":"29839","sodUtc8":"30788.7","volCcy24h":"3764.42","vol24h":"376442","ts":"1654166126913"}]}"#; assert_eq!( 1654166126913, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USDT-220624", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn inverse_swap() { let raw_msg = r#"{"arg":{"channel":"tickers","instId":"BTC-USD-SWAP"},"data":[{"instType":"SWAP","instId":"BTC-USD-SWAP","last":"29937.6","lastSz":"2","askPx":"29933","askSz":"34","bidPx":"29932.9","bidSz":"66","open24h":"31572.7","high24h":"31885.6","low24h":"29277.5","sodUtc0":"29777.9","sodUtc8":"30715","volCcy24h":"17799.3208","vol24h":"5412510","ts":"1654166220361"}]}"#; assert_eq!( 1654166220361, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn linear_swap() { let raw_msg = r#"{"arg":{"channel":"tickers","instId":"BTC-USDT-SWAP"},"data":[{"instType":"SWAP","instId":"BTC-USDT-SWAP","last":"29963","lastSz":"2","askPx":"29960","askSz":"12","bidPx":"29959.9","bidSz":"431","open24h":"31589.3","high24h":"31907.2","low24h":"29302","sodUtc0":"29805","sodUtc8":"30753.7","volCcy24h":"108540.53","vol24h":"10854053","ts":"1654166233877"}]}"#; assert_eq!( 1654166233877, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USDT-SWAP", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap() ); } #[test] fn option() { let raw_msg = r#"{"arg":{"channel":"tickers","instId":"BTC-USD-220624-50000-C"},"data":[{"instType":"OPTION","instId":"BTC-USD-220624-50000-C","last":"0.0005","lastSz":"6","askPx":"0.0015","askSz":"330","bidPx":"","bidSz":"","open24h":"0.0005","high24h":"0.0005","low24h":"0.0005","sodUtc0":"0.0005","sodUtc8":"0.0005","volCcy24h":"0","vol24h":"0","ts":"1654166283149"}]}"#; assert_eq!( 1654166283149, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-220624-50000-C", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap() ); } } #[cfg(test)] mod l2_snapshot { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp}; #[test] fn spot() { let raw_msg = r#"{"code":"0","msg":"","data":[{"asks":[["29692.5","0.10951348","0","5"],["29692.6","0.00631557","0","1"],["29692.8","0.10662911","0","1"]],"bids":[["29692.4","0.43986254","0","2"],["29691.2","0.33792","0","1"],["29690","0.39370474","0","2"]],"ts":"1654328918680"}]}"#; assert_eq!( 1654328918680, extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap() ); assert_eq!("NONE", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()); } #[test] fn inverse_future() { let raw_msg = r#"{"code":"0","msg":"","data":[{"asks":[["29678.9","11","0","1"],["29679","5","0","1"],["29679.3","14","0","2"]],"bids":[["29673.5","8","0","1"],["29673.4","14","0","1"],["29673.1","285","0","1"]],"ts":"1654329601749"}]}"#; assert_eq!( 1654329601749, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "NONE", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn linear_future() { let raw_msg = r#"{"code":"0","msg":"","data":[{"asks":[["29756.3","5","0","1"],["29756.4","90","0","1"],["29761.1","7","0","1"]],"bids":[["29755.4","95","0","1"],["29755.3","124","0","1"],["29755","128","0","1"]],"ts":"1654329646278"}]}"#; assert_eq!( 1654329646278, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "NONE", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn inverse_swap() { let raw_msg = r#"{"code":"0","msg":"","data":[{"asks":[["29671.3","12","0","3"],["29675.7","10","0","1"],["29676.9","38","0","1"]],"bids":[["29671.2","759","0","9"],["29670.8","10","0","1"],["29670.2","4","0","1"]],"ts":"1654329603386"}]}"#; assert_eq!( 1654329603386, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "NONE", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn linear_swap() { let raw_msg = r#"{"code":"0","msg":"","data":[{"asks":[["29701.7","2","0","1"],["29702.9","19","0","1"],["29703.4","20","0","4"]],"bids":[["29701.6","5","0","1"],["29701.5","2","0","1"],["29700.4","2","0","2"]],"ts":"1654329607417"}]}"#; assert_eq!( 1654329607417, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!("NONE", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()); } #[test] fn option() { let raw_msg = r#"{"code":"0","msg":"","data":[{"asks":[["0.0155","305","0","1"]],"bids":[["0.011","305","0","1"]],"ts":"1654329628580"}]}"#; assert_eq!( 1654329628580, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!("NONE", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()); } } #[cfg(test)] mod open_interest { use super::EXCHANGE_NAME; use crypto_market_type::MarketType; use crypto_msg_parser::{extract_symbol, extract_timestamp}; #[test] fn inverse_future() { let raw_msg = r#"{"code":"0","data":[{"instId":"BTC-USD-220520","instType":"FUTURES","oi":"0","oiCcy":"0","ts":"1654348172899"},{"instId":"BTC-USD-220527","instType":"FUTURES","oi":"0","oiCcy":"0","ts":"1654348172899"}],"msg":""}"#; assert_eq!( 1654348172899, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!("ALL", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()); let raw_msg = r#"{"code":"0","data":[{"instId":"BTC-USD-220520","instType":"FUTURES","oi":"0","oiCcy":"0","ts":"1654348172899"}],"msg":""}"#; assert_eq!( 1654348172899, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!( "BTC-USD-220520", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap() ); } #[test] fn linear_future() { let raw_msg = r#"{"code":"0","data":[{"instId":"BTC-USD-220520","instType":"FUTURES","oi":"0","oiCcy":"0","ts":"1654348596037"},{"instId":"BTC-USD-220527","instType":"FUTURES","oi":"0","oiCcy":"0","ts":"1654348596037"}],"msg":""}"#; assert_eq!( 1654348596037, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!("ALL", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()); } #[test] fn inverse_swap() { let raw_msg = r#"{"code":"0","data":[{"instId":"BTC-USD-SWAP","instType":"SWAP","oi":"4092973","oiCcy":"13840.048827662696883","ts":"1654348683853"},{"instId":"ETH-USD-SWAP","instType":"SWAP","oi":"21795246","oiCcy":"123562.1205163528751467","ts":"1654348683853"}],"msg":""}"#; assert_eq!( 1654348683853, extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap() ); assert_eq!("ALL", extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()); } #[test] fn linear_swap() { let raw_msg = r#"{"code":"0","data":[{"instId":"BTC-USD-SWAP","instType":"SWAP","oi":"4093058","oiCcy":"13842.2084993270069734","ts":"1654348739678"},{"instId":"ETH-USD-SWAP","instType":"SWAP","oi":"21797983","oiCcy":"123701.0640410861731408","ts":"1654348739678"}],"msg":""}"#; assert_eq!( 1654348739678, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!("ALL", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()); } #[test] fn option() { let raw_msg = r#"{"code":"0","data":[{"instId":"BTC-USD-220520-18000-C","instType":"OPTION","oi":"0","oiCcy":"0","ts":"1654348880968"},{"instId":"BTC-USD-220520-20000-C","instType":"OPTION","oi":"0","oiCcy":"0","ts":"1654348906381"}],"msg":""}"#; assert_eq!( 1654348906381, extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap() ); assert_eq!("ALL", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()); } }