mod utils;
const EXCHANGE_NAME: &str = "bitget";
#[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};
#[test]
fn spot() {
let raw_msg = r#"{"action":"update","arg":{"instType":"sp","channel":"trade","instId":"BTCUSDT"},"data":[["1653873778747","29443.24","0.4134","buy"]]}"#;
let trade = &parse_trade(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()[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!(
1653873778747,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(trade.timestamp, 1653873778747);
assert_eq!(trade.price, 29443.24);
assert_eq!(trade.quantity_base, 0.4134);
assert_eq!(trade.quantity_quote, 29443.24 * 0.4134);
assert_eq!(trade.quantity_contract, None);
assert_eq!(trade.side, TradeSide::Buy);
}
#[test]
fn inverse_swap() {
let raw_msg = r#"{"action":"update","arg":{"instType":"mc","channel":"trade","instId":"BTCUSD"},"data":[["1653881896935","30285","0.024","buy"]]}"#;
let trade = &parse_trade(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()[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!(
1653881896935,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(trade.timestamp, 1653881896935);
assert_eq!(trade.price, 30285.0);
assert_eq!(trade.quantity_base, 0.024);
assert_eq!(trade.quantity_quote, 30285.0 * 0.024);
assert_eq!(trade.quantity_contract, Some(0.024));
assert_eq!(trade.side, TradeSide::Buy);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"action":"update","arg":{"instType":"mc","channel":"trade","instId":"BTCUSDT"},"data":[["1653882567817","30322.5","1.117","buy"],["1653882567817","30322","1.566","buy"]]}"#;
let trades = &parse_trade(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap();
assert_eq!(2, trades.len());
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!(
1653882567817,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(trade.timestamp, 1653882567817);
assert_eq!(trade.price, 30322.5);
assert_eq!(trade.quantity_base, 1.117);
assert_eq!(trade.quantity_quote, 30322.5 * 1.117);
assert_eq!(trade.quantity_contract, Some(1.117));
assert_eq!(trade.side, TradeSide::Buy);
}
}
#[cfg(test)]
mod l2_event {
use super::EXCHANGE_NAME;
use crypto_market_type::MarketType;
use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_l2};
use crypto_msg_type::MessageType;
#[test]
fn spot() {
let raw_msg = r#"{"action":"update","arg":{"instType":"sp","channel":"books","instId":"BTCUSDT"},"data":[{"asks":[["30266.73","0.0109"],["30266.77","0.0117"],["30266.94","2.5135"]],"bids":[["30266.57","0.0119"],["30266.53","0.0130"],["30265.49","0.0140"] ],"checksum":1732241839,"ts":"1653885248245"}]}"#;
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!(
1653885248245,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1653885248245);
assert_eq!(orderbook.seq_id, None);
assert_eq!(orderbook.prev_seq_id, None);
assert_eq!(orderbook.bids[0].price, 30266.57);
assert_eq!(orderbook.bids[0].quantity_base, 0.0119);
assert_eq!(orderbook.bids[0].quantity_quote, 30266.57 * 0.0119);
assert_eq!(orderbook.bids[0].quantity_contract, None);
assert_eq!(orderbook.bids[2].price, 30265.49);
assert_eq!(orderbook.bids[2].quantity_base, 0.0140);
assert_eq!(orderbook.bids[2].quantity_quote, 30265.49 * 0.0140);
assert_eq!(orderbook.bids[0].quantity_contract, None);
assert_eq!(orderbook.asks[0].price, 30266.73);
assert_eq!(orderbook.asks[0].quantity_base, 0.0109);
assert_eq!(orderbook.asks[0].quantity_quote, 30266.73 * 0.0109);
assert_eq!(orderbook.asks[0].quantity_contract, None);
assert_eq!(orderbook.asks[2].price, 30266.94);
assert_eq!(orderbook.asks[2].quantity_base, 2.5135);
assert_eq!(orderbook.asks[2].quantity_quote, 30266.94 * 2.5135);
assert_eq!(orderbook.asks[2].quantity_contract, None);
}
#[test]
fn inverse_swap() {
let raw_msg = r#"{"action":"update","arg":{"instType":"mc","channel":"books","instId":"BTCUSD"},"data":[{"asks":[["30693.5","0.073"],["30694.0","0.064"],["30695.0","18.601"]],"bids":[["30678.0","12.693"],["30675.5","0.091"],["30674.0","22.504"]],"checksum":1033568482,"ts":"1653935348839"}]}"#;
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!(
1653935348839,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1653935348839);
assert_eq!(orderbook.seq_id, None);
assert_eq!(orderbook.prev_seq_id, None);
assert_eq!(orderbook.bids[0].price, 30678.0);
assert_eq!(orderbook.bids[0].quantity_base, 12.693);
assert_eq!(orderbook.bids[0].quantity_quote, 30678.0 * 12.693);
assert_eq!(orderbook.bids[0].quantity_contract, Some(12.693));
assert_eq!(orderbook.bids[2].price, 30674.0);
assert_eq!(orderbook.bids[2].quantity_base, 22.504);
assert_eq!(orderbook.bids[2].quantity_quote, 30674.0 * 22.504);
assert_eq!(orderbook.bids[2].quantity_contract, Some(22.504));
assert_eq!(orderbook.asks[0].price, 30693.5);
assert_eq!(orderbook.asks[0].quantity_base, 0.073);
assert_eq!(orderbook.asks[0].quantity_quote, 30693.5 * 0.073);
assert_eq!(orderbook.asks[0].quantity_contract, Some(0.073));
assert_eq!(orderbook.asks[2].price, 30695.0);
assert_eq!(orderbook.asks[2].quantity_base, 18.601);
assert_eq!(orderbook.asks[2].quantity_quote, 30695.0 * 18.601);
assert_eq!(orderbook.asks[2].quantity_contract, Some(18.601));
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"action":"update","arg":{"instType":"mc","channel":"books","instId":"BTCUSDT"},"data":[{"asks":[["30677.5","17.098"],["30678.0","62.033"],["30679.0","5.129"]],"bids":[["30673.5","5.264"],["30673.0","18.938"],["30672.5","10.378"]],"checksum":-1093370704,"ts":"1653935972126"}]}"#;
let orderbook = &parse_l2(EXCHANGE_NAME, MarketType::LinearSwap, 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::LinearSwap,
MessageType::L2Event,
"BTC/USDT".to_string(),
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(),
orderbook,
raw_msg,
);
assert_eq!(
1653935972126,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1653935972126);
assert_eq!(orderbook.seq_id, None);
assert_eq!(orderbook.prev_seq_id, None);
assert_eq!(orderbook.bids[0].price, 30673.5);
assert_eq!(orderbook.bids[0].quantity_base, 5.264);
assert_eq!(orderbook.bids[0].quantity_quote, 30673.5 * 5.264);
assert_eq!(orderbook.bids[0].quantity_contract, Some(5.264));
assert_eq!(orderbook.bids[2].price, 30672.5);
assert_eq!(orderbook.bids[2].quantity_base, 10.378);
assert_eq!(orderbook.bids[2].quantity_quote, 30672.5 * 10.378);
assert_eq!(orderbook.bids[2].quantity_contract, Some(10.378));
assert_eq!(orderbook.asks[0].price, 30677.5);
assert_eq!(orderbook.asks[0].quantity_base, 17.098);
assert_eq!(orderbook.asks[0].quantity_quote, 30677.5 * 17.098);
assert_eq!(orderbook.asks[0].quantity_contract, Some(17.098));
assert_eq!(orderbook.asks[2].price, 30679.0);
assert_eq!(orderbook.asks[2].quantity_base, 5.129);
assert_eq!(orderbook.asks[2].quantity_quote, 30679.0 * 5.129);
assert_eq!(orderbook.asks[2].quantity_contract, Some(5.129));
}
}
#[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};
use crypto_msg_type::MessageType;
#[test]
fn spot() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"sp","channel":"books5","instId":"BTCUSDT"},"data":[{"asks":[["30682.29","0.0119"],["30682.33","0.0127"],["30682.37","0.0213"],["30682.41","0.0560"],["30682.45","0.1474"]],"bids":[["30682.15","0.0122"],["30682.11","0.0132"],["30682.07","0.0114"],["30682.03","0.0122"],["30681.99","0.0118"]],"ts":"1653936946292"}]}"#;
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!(
1653936946292,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1653936946292);
assert_eq!(orderbook.seq_id, None);
assert_eq!(orderbook.prev_seq_id, None);
assert_eq!(orderbook.bids[0].price, 30682.15);
assert_eq!(orderbook.bids[0].quantity_base, 0.0122);
assert_eq!(orderbook.bids[0].quantity_quote, 30682.15 * 0.0122);
assert_eq!(orderbook.bids[0].quantity_contract, None);
assert_eq!(orderbook.bids[4].price, 30681.99);
assert_eq!(orderbook.bids[4].quantity_base, 0.0118);
assert_eq!(orderbook.bids[4].quantity_quote, 30681.99 * 0.0118);
assert_eq!(orderbook.bids[4].quantity_contract, None);
assert_eq!(orderbook.asks[0].price, 30682.29);
assert_eq!(orderbook.asks[0].quantity_base, 0.0119);
assert_eq!(orderbook.asks[0].quantity_quote, 30682.29 * 0.0119);
assert_eq!(orderbook.asks[0].quantity_contract, None);
assert_eq!(orderbook.asks[4].price, 30682.45);
assert_eq!(orderbook.asks[4].quantity_base, 0.1474);
assert_eq!(orderbook.asks[4].quantity_quote, 30682.45 * 0.1474);
assert_eq!(orderbook.asks[4].quantity_contract, None);
}
#[test]
fn inverse_swap() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"mc","channel":"books5","instId":"BTCUSD"},"data":[{"asks":[["30669.0","0.763"],["30669.5","3.036"],["30670.0","0.103"],["30670.5","1.955"],["30671.5","9.537"]],"bids":[["30667.5","0.093"],["30667.0","25.104"],["30666.5","20.913"],["30666.0","20.223"],["30665.5","0.695"]],"ts":"1653937135034"}]}"#;
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!(
1653937135034,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1653937135034);
assert_eq!(orderbook.seq_id, None);
assert_eq!(orderbook.prev_seq_id, None);
assert_eq!(orderbook.bids[0].price, 30667.5);
assert_eq!(orderbook.bids[0].quantity_base, 0.093);
assert_eq!(orderbook.bids[0].quantity_quote, 30667.5 * 0.093);
assert_eq!(orderbook.bids[0].quantity_contract, Some(0.093));
assert_eq!(orderbook.bids[4].price, 30665.5);
assert_eq!(orderbook.bids[4].quantity_base, 0.695);
assert_eq!(orderbook.bids[4].quantity_quote, 30665.5 * 0.695);
assert_eq!(orderbook.bids[4].quantity_contract, Some(0.695));
assert_eq!(orderbook.asks[0].price, 30669.0);
assert_eq!(orderbook.asks[0].quantity_base, 0.763);
assert_eq!(orderbook.asks[0].quantity_quote, 30669.0 * 0.763);
assert_eq!(orderbook.asks[0].quantity_contract, Some(0.763));
assert_eq!(orderbook.asks[4].price, 30671.5);
assert_eq!(orderbook.asks[4].quantity_base, 9.537);
assert_eq!(orderbook.asks[4].quantity_quote, 30671.5 * 9.537);
assert_eq!(orderbook.asks[4].quantity_contract, Some(9.537));
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"mc","channel":"books5","instId":"BTCUSDT"},"data":[{"asks":[["30678.0","0.500"],["30679.0","56.116"],["30679.5","7.024"],["30680.0","2.916"],["30680.5","3.098"]],"bids":[["30677.5","0.953"],["30677.0","4.152"],["30676.5","2.030"],["30676.0","24.110"],["30675.5","44.509"]],"ts":"1653937451315"}]}"#;
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!(
1653937451315,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1653937451315);
assert_eq!(orderbook.seq_id, None);
assert_eq!(orderbook.prev_seq_id, None);
assert_eq!(orderbook.bids[0].price, 30677.5);
assert_eq!(orderbook.bids[0].quantity_base, 0.953);
assert_eq!(orderbook.bids[0].quantity_quote, 30677.5 * 0.953);
assert_eq!(orderbook.bids[0].quantity_contract, Some(0.953));
assert_eq!(orderbook.bids[4].price, 30675.5);
assert_eq!(orderbook.bids[4].quantity_base, 44.509);
assert_eq!(orderbook.bids[4].quantity_quote, 30675.5 * 44.509);
assert_eq!(orderbook.bids[4].quantity_contract, Some(44.509));
assert_eq!(orderbook.asks[0].price, 30678.0);
assert_eq!(orderbook.asks[0].quantity_base, 0.500);
assert_eq!(orderbook.asks[0].quantity_quote, 30678.0 * 0.500);
assert_eq!(orderbook.asks[0].quantity_contract, Some(0.500));
assert_eq!(orderbook.asks[4].price, 30680.5);
assert_eq!(orderbook.asks[4].quantity_base, 3.098);
assert_eq!(orderbook.asks[4].quantity_quote, 30680.5 * 3.098);
assert_eq!(orderbook.asks[4].quantity_contract, Some(3.098));
}
}
#[cfg(test)]
mod funding_rate {
use super::EXCHANGE_NAME;
use crypto_market_type::MarketType;
use crypto_msg_parser::parse_funding_rate;
#[test]
fn inverse_swap() {
let raw_msg = r#"{"data":[{"funding_rate":"0.000258514264","funding_time":"1617346800000","instrument_id":"btcusd"}],"table":"swap/funding_rate"}"#;
let funding_rates =
&parse_funding_rate(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).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!(funding_rates[0].pair, "BTC/USD".to_string());
assert_eq!(funding_rates[0].funding_rate, 0.000258514264);
assert_eq!(funding_rates[0].funding_time, 1617346800000);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"data":[{"funding_rate":"0.000106539854","funding_time":"1617346800000","instrument_id":"cmt_btcusdt"}],"table":"swap/funding_rate"}"#;
let funding_rates =
&parse_funding_rate(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap();
assert_eq!(funding_rates.len(), 1);
for rate in funding_rates.iter() {
crate::utils::check_funding_rate_fields(
EXCHANGE_NAME,
MarketType::LinearSwap,
rate,
raw_msg,
);
}
assert_eq!(funding_rates[0].pair, "BTC/USDT".to_string());
assert_eq!(funding_rates[0].funding_rate, 0.000106539854);
assert_eq!(funding_rates[0].funding_time, 1617346800000);
}
}
#[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_snapshot() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"sp","channel":"candle1m","instId":"BTCUSDT"},"data":[["1654017060000","32173.42","32173.42","32154.98","32154.98","6.7112"],["1654017120000","32154.98","32171.66","32154.83","32157.96","10.3505"]]}"#;
assert_eq!(
1654017120000,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSDT_SPBL",
extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()
);
let arr = parse_candlestick(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap();
assert_eq!(2, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("BTCUSDT_SPBL", candlestick_msg.symbol);
assert_eq!("BTC/USDT", candlestick_msg.pair);
assert_eq!(1654017060000, candlestick_msg.timestamp);
assert_eq!(1654017000000, candlestick_msg.begin_time);
assert_eq!("1m", candlestick_msg.period);
assert_eq!(32173.42, candlestick_msg.open);
assert_eq!(32173.42, candlestick_msg.high);
assert_eq!(32154.98, candlestick_msg.low);
assert_eq!(32154.98, candlestick_msg.close);
assert_eq!(6.7112, candlestick_msg.volume);
assert_eq!(None, candlestick_msg.quote_volume);
}
#[test]
fn spot_update() {
let raw_msg = r#"{"action":"update","arg":{"instType":"sp","channel":"candle1m","instId":"BTCUSDT"},"data":[["1654077000000","31682.39","31683.63","31674.84","31676.58","20.3826"]]}"#;
assert_eq!(
1654077000000,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSDT_SPBL",
extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()
);
let arr = parse_candlestick(EXCHANGE_NAME, MarketType::Spot, raw_msg, None).unwrap();
assert_eq!(1, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("BTCUSDT_SPBL", candlestick_msg.symbol);
assert_eq!("BTC/USDT", candlestick_msg.pair);
assert_eq!(1654077000000, candlestick_msg.timestamp);
assert_eq!(1654076940000, candlestick_msg.begin_time);
assert_eq!("1m", candlestick_msg.period);
assert_eq!(31682.39, candlestick_msg.open);
assert_eq!(31683.63, candlestick_msg.high);
assert_eq!(31674.84, candlestick_msg.low);
assert_eq!(31676.58, candlestick_msg.close);
assert_eq!(20.3826, candlestick_msg.volume);
assert_eq!(None, candlestick_msg.quote_volume);
}
#[test]
fn inverse_swap_snapshot() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"mc","channel":"candle1m","instId":"BTCUSD"},"data":[["1654017420000","31974","31992.5","31922","31935","9.197"],["1654017480000","31935","31988.5","31914.5","31938.5","7.004"]]}"#;
assert_eq!(
1654017480000,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSD_DMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()
);
let arr = parse_candlestick(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap();
assert_eq!(2, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("BTCUSD_DMCBL", candlestick_msg.symbol);
assert_eq!("BTC/USD", candlestick_msg.pair);
assert_eq!(1654017420000, candlestick_msg.timestamp);
assert_eq!(1654017360000, candlestick_msg.begin_time);
assert_eq!("1m", candlestick_msg.period);
assert_eq!(31974.0, candlestick_msg.open);
assert_eq!(31992.5, candlestick_msg.high);
assert_eq!(31922.0, candlestick_msg.low);
assert_eq!(31935.0, candlestick_msg.close);
assert_eq!(9.197, candlestick_msg.volume);
assert_eq!(None, candlestick_msg.quote_volume);
}
#[test]
fn inverse_swap_update() {
let raw_msg = r#"{"action":"update","arg":{"instType":"mc","channel":"candle1m","instId":"BTCUSD"},"data":[["1654077360000","31652","31653.5","31651.5","31652","0.227"]]}"#;
assert_eq!(
1654077360000,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSD_DMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()
);
let arr = parse_candlestick(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap();
assert_eq!(1, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("BTCUSD_DMCBL", candlestick_msg.symbol);
assert_eq!("BTC/USD", candlestick_msg.pair);
assert_eq!(1654077360000, candlestick_msg.timestamp);
assert_eq!(1654077300000, candlestick_msg.begin_time);
assert_eq!("1m", candlestick_msg.period);
assert_eq!(31652.0, candlestick_msg.open);
assert_eq!(31653.5, candlestick_msg.high);
assert_eq!(31651.5, candlestick_msg.low);
assert_eq!(31652.0, candlestick_msg.close);
assert_eq!(0.227, candlestick_msg.volume);
assert_eq!(None, candlestick_msg.quote_volume);
}
#[test]
fn linear_swap_snapshot() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"mc","channel":"candle1m","instId":"BTCUSDT"},"data":[["1654017660000","31966.5","31966.5","31947","31952.5","111.769"],["1654017720000","31952.5","31974.5","31939","31940","109.557"]]}"#;
assert_eq!(
1654017720000,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSDT_UMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()
);
let arr = parse_candlestick(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap();
assert_eq!(2, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("BTCUSDT_UMCBL", candlestick_msg.symbol);
assert_eq!("BTC/USDT", candlestick_msg.pair);
assert_eq!(1654017660000, candlestick_msg.timestamp);
assert_eq!(1654017600000, candlestick_msg.begin_time);
assert_eq!("1m", candlestick_msg.period);
assert_eq!(31966.5, candlestick_msg.open);
assert_eq!(31966.5, candlestick_msg.high);
assert_eq!(31947.0, candlestick_msg.low);
assert_eq!(31952.5, candlestick_msg.close);
assert_eq!(111.769, candlestick_msg.volume);
assert_eq!(None, candlestick_msg.quote_volume);
}
#[test]
fn linear_swap_update() {
let raw_msg = r#"{"action":"update","arg":{"instType":"mc","channel":"candle1m","instId":"BTCUSDT"},"data":[["1654077600000","31676.5","31676.5","31671","31671","5.639"]]}"#;
assert_eq!(
1654077600000,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSDT_UMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()
);
let arr = parse_candlestick(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap();
assert_eq!(1, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("BTCUSDT_UMCBL", candlestick_msg.symbol);
assert_eq!("BTC/USDT", candlestick_msg.pair);
assert_eq!(1654077600000, candlestick_msg.timestamp);
assert_eq!(1654077540000, candlestick_msg.begin_time);
assert_eq!("1m", candlestick_msg.period);
assert_eq!(31676.5, candlestick_msg.open);
assert_eq!(31676.5, candlestick_msg.high);
assert_eq!(31671.0, candlestick_msg.low);
assert_eq!(31671.0, candlestick_msg.close);
assert_eq!(5.639, candlestick_msg.volume);
assert_eq!(None, candlestick_msg.quote_volume);
}
}
#[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#"{"action":"snapshot","arg":{"instType":"sp","channel":"ticker","instId":"BTCUSDT"},"data":[{"instId":"BTCUSDT","last":"29948.21","open24h":"30726.18","high24h":"30741.06","low24h":"29336.95","bestBid":"29944.390000","bestAsk":"29944.550000","baseVolume":"24658.6272","quoteVolume":"749224809.9118","ts":1654160360101,"labeId":0}]}"#;
assert_eq!(
1654160360101,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSDT_SPBL",
extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()
);
}
#[test]
fn inverse_swap() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"mc","channel":"ticker","instId":"BTCUSD"},"data":[{"instId":"BTCUSD","last":"29898.50","bestAsk":"29899","bestBid":"29898","high24h":"30706.50","low24h":"29270.50","priceChangePercent":"-0.02","capitalRate":"0.000100","nextSettleTime":1654182000000,"systemTime":1654160828664,"markPrice":"29897.79","indexPrice":"29906.49","holding":"6166.235","baseVolume":"6601.040","quoteVolume":"201847558.263"}]}"#;
assert_eq!(
1654160828664,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSD_DMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap()
);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"action":"snapshot","arg":{"instType":"mc","channel":"ticker","instId":"BTCUSDT"},"data":[{"instId":"BTCUSDT","last":"29905.50","bestAsk":"29905.5","bestBid":"29904.5","high24h":"30731.50","low24h":"29293.00","priceChangePercent":"-0.02","capitalRate":"0.000100","nextSettleTime":1654182000000,"systemTime":1654160847314,"markPrice":"29906.42","indexPrice":"29928.32","holding":"87338.493","baseVolume":"214176.417","quoteVolume":"6536325903.110"}]}"#;
assert_eq!(
1654160847314,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(
"BTCUSDT_UMCBL",
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":"00000","msg":"success","requestTime":1654232411024,"data":{"asks":[["30413.33","0.0141"],["30413.37","0.0112"],["30413.41","0.0179"]],"bids":[["30413.27","0.0296"],["30413.23","0.0484"],["30413.19","0.1272"]],"timestamp":"1654232411024"}}"#;
assert_eq!("NONE", extract_symbol(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap());
assert_eq!(
1654232411024,
extract_timestamp(EXCHANGE_NAME, MarketType::Spot, raw_msg).unwrap().unwrap()
);
}
#[test]
fn inverse_swap() {
let raw_msg = r#"{"code":"00000","msg":"success","requestTime":1654234201087,"data":{"asks":[["30521","1.661"],["30521.5","2.312"],["30522","0.139"]],"bids":[["3.052E+4","0.256"],["30519.5","0.482"],["30519","0.079"]],"timestamp":"1654234201087"}}"#;
assert_eq!(
"NONE",
extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()
);
assert_eq!(
1654234201087,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"code":"00000","msg":"success","requestTime":1654234229348,"data":{"asks":[["30544","13.904"],["30544.5","2.678"],["30545","4.923"]],"bids":[["30543","0.756"],["30542.5","0.749"],["30542","15.438"]],"timestamp":"1654234229348"}}"#;
assert_eq!("NONE", extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap());
assert_eq!(
1654234229348,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().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_swap() {
let raw_msg = r#"{"code":"00000","msg":"success","requestTime":1654337704617,"data":{"symbol":"BTCUSD_DMCBL","amount":"5030.748","timestamp":"1654337704617"}}"#;
assert_eq!(
"BTCUSD_DMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()
);
assert_eq!(
1654337704617,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap().unwrap()
);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"code":"00000","msg":"success","requestTime":1654337723059,"data":{"symbol":"BTCUSDT_UMCBL","amount":"89481.932","timestamp":"1654337723059"}}"#;
assert_eq!(
"BTCUSDT_UMCBL",
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()
);
assert_eq!(
1654337723059,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
}
}
#[cfg(test)]
mod before20220429 {
#[cfg(test)]
mod trade {
use super::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 inverse_swap() {
let raw_msg = r#"{"data":[{"instrument_id":"btcusd","price":"58722.0","side":"sell","size":"158","timestamp":"1616236107276"},{"instrument_id":"btcusd","price":"58722.0","side":"sell","size":"450","timestamp":"1616236107276"},{"instrument_id":"btcusd","price":"58722.0","side":"sell","size":"762","timestamp":"1616236107276"}],"table":"swap/trade"}"#;
let trades = &parse_trade(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap();
assert_eq!(trades.len(), 3);
for trade in trades.iter() {
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!(trade.side, TradeSide::Sell);
}
assert_eq!(
1616236107276,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg)
.unwrap()
.unwrap()
);
assert_eq!(trades[0].quantity_base, 158.0 / 58722.0);
assert_eq!(trades[0].quantity_quote, 158.0);
assert_eq!(trades[0].quantity_contract, Some(158.0));
assert_eq!(trades[1].quantity_base, 450.0 / 58722.0);
assert_eq!(trades[1].quantity_quote, 450.0);
assert_eq!(trades[1].quantity_contract, Some(450.0));
assert_eq!(trades[2].quantity_base, 762.0 / 58722.0);
assert_eq!(trades[2].quantity_quote, 762.0);
assert_eq!(trades[2].quantity_contract, Some(762.0));
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"data":[{"instrument_id":"cmt_btcusdt","price":"58784.0","side":"sell","size":"1265","timestamp":"1616236212569"},{"instrument_id":"cmt_btcusdt","price":"58784.0","side":"sell","size":"25","timestamp":"1616236212569"},{"instrument_id":"cmt_btcusdt","price":"58784.0","side":"sell","size":"181","timestamp":"1616236212569"}],"table":"swap/trade"}"#;
let trades = &parse_trade(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap();
assert_eq!(trades.len(), 3);
for trade in trades.iter() {
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!(trade.side, TradeSide::Sell);
}
assert_eq!(
1616236212569,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(trades[0].quantity_base, round(1265.0 * 0.001));
assert_eq!(trades[1].quantity_base, 25.0 * 0.001);
assert_eq!(trades[2].quantity_base, 181.0 * 0.001);
}
}
#[cfg(test)]
mod funding_rate {
use super::super::EXCHANGE_NAME;
use crypto_market_type::MarketType;
use crypto_msg_parser::parse_funding_rate;
#[test]
fn inverse_swap() {
let raw_msg = r#"{"data":[{"funding_rate":"0.000258514264","funding_time":"1617346800000","instrument_id":"btcusd"}],"table":"swap/funding_rate"}"#;
let funding_rates =
&parse_funding_rate(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).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!(funding_rates[0].pair, "BTC/USD".to_string());
assert_eq!(funding_rates[0].funding_rate, 0.000258514264);
assert_eq!(funding_rates[0].funding_time, 1617346800000);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"data":[{"funding_rate":"0.000106539854","funding_time":"1617346800000","instrument_id":"cmt_btcusdt"}],"table":"swap/funding_rate"}"#;
let funding_rates =
&parse_funding_rate(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap();
assert_eq!(funding_rates.len(), 1);
for rate in funding_rates.iter() {
crate::utils::check_funding_rate_fields(
EXCHANGE_NAME,
MarketType::LinearSwap,
rate,
raw_msg,
);
}
assert_eq!(funding_rates[0].pair, "BTC/USDT".to_string());
assert_eq!(funding_rates[0].funding_rate, 0.000106539854);
assert_eq!(funding_rates[0].funding_time, 1617346800000);
}
}
#[cfg(test)]
mod l2_orderbook {
use super::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 linear_swap_snapshot() {
let raw_msg = r#"{"action":"partial","data":[{"asks":[["34589.0","507"],["34589.5","958"],["34590.0","6751"],["34590.5","898"],["34591.0","1987"]],"bids":[["34588.0","1199"],["34587.0","1339"],["34586.5","506"],["34586.0","4018"],["34585.0","1259"]],"instrument_id":"cmt_btcusdt","timestamp":"1622432420458"}],"table":"swap/depth"}"#;
let orderbook =
&parse_l2(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::L2Event,
"BTC/USDT".to_string(),
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(),
orderbook,
raw_msg,
);
assert_eq!(
1622432420458,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1622432420458);
assert_eq!(orderbook.bids[0].price, 34588.0);
assert_eq!(orderbook.bids[0].quantity_base, 1.199);
assert_eq!(orderbook.bids[0].quantity_quote, 1.199 * 34588.0);
assert_eq!(orderbook.bids[0].quantity_contract.unwrap(), 1199.0);
assert_eq!(orderbook.bids[4].price, 34585.0);
assert_eq!(orderbook.bids[4].quantity_base, 1.259);
assert_eq!(orderbook.bids[4].quantity_quote, 1.259 * 34585.0);
assert_eq!(orderbook.bids[4].quantity_contract.unwrap(), 1259.0);
assert_eq!(orderbook.asks[0].price, 34589.0);
assert_eq!(orderbook.asks[0].quantity_base, 0.507);
assert_eq!(orderbook.asks[0].quantity_quote, 0.507 * 34589.0);
assert_eq!(orderbook.asks[0].quantity_contract.unwrap(), 507.0);
assert_eq!(orderbook.asks[4].price, 34591.0);
assert_eq!(orderbook.asks[4].quantity_base, 1.987);
assert_eq!(orderbook.asks[4].quantity_quote, round(1.987 * 34591.0));
assert_eq!(orderbook.asks[4].quantity_contract.unwrap(), 1987.0);
}
#[test]
fn linear_swap_update() {
let raw_msg = r#"{"action":"update","data":[{"asks":[["34523","510"]],"bids":[["34522","9079"],["34521.5","31174"]],"instrument_id":"cmt_btcusdt","timestamp":"1622434075797"}],"table":"swap/depth"}"#;
let orderbook =
&parse_l2(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap()[0];
assert_eq!(orderbook.asks.len(), 1);
assert_eq!(orderbook.bids.len(), 2);
assert!(!orderbook.snapshot);
crate::utils::check_orderbook_fields(
EXCHANGE_NAME,
MarketType::LinearSwap,
MessageType::L2Event,
"BTC/USDT".to_string(),
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(),
orderbook,
raw_msg,
);
assert_eq!(
1622434075797,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1622434075797);
assert_eq!(orderbook.bids[0].price, 34522.0);
assert_eq!(orderbook.bids[0].quantity_base, 9.079);
assert_eq!(orderbook.bids[0].quantity_quote, 9.079 * 34522.0);
assert_eq!(orderbook.bids[0].quantity_contract.unwrap(), 9079.0);
assert_eq!(orderbook.bids[1].price, 34521.5);
assert_eq!(orderbook.bids[1].quantity_base, 31.174);
assert_eq!(orderbook.bids[1].quantity_quote, 31.174 * 34521.5);
assert_eq!(orderbook.bids[1].quantity_contract.unwrap(), 31174.0);
assert_eq!(orderbook.asks[0].price, 34523.0);
assert_eq!(orderbook.asks[0].quantity_base, 0.51);
assert_eq!(orderbook.asks[0].quantity_quote, 0.51 * 34523.0);
assert_eq!(orderbook.asks[0].quantity_contract.unwrap(), 510.0);
}
#[test]
fn inverse_swap_snapshot() {
let raw_msg = r#"{"action":"partial","data":[{"asks":[["34880.5","506"],["34881.0","4496"],["34881.5","73280"],["34882.0","84782"],["34882.5","135651"]],"bids":[["34879.0","14946"],["34878.5","24386"],["34878.0","10048"],["34877.5","161361"],["34877.0","61292"]],"instrument_id":"btcusd","timestamp":"1622426574770"}],"table":"swap/depth"}"#;
let orderbook =
&parse_l2(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::L2Event,
"BTC/USD".to_string(),
extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap(),
orderbook,
raw_msg,
);
assert_eq!(
1622426574770,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1622426574770);
assert_eq!(orderbook.bids[0].price, 34879.0);
assert_eq!(orderbook.bids[0].quantity_base, 14946.0 / 34879.0);
assert_eq!(orderbook.bids[0].quantity_quote, 14946.0);
assert_eq!(orderbook.bids[0].quantity_contract.unwrap(), 14946.0);
assert_eq!(orderbook.bids[4].price, 34877.0);
assert_eq!(orderbook.bids[4].quantity_base, 61292.0 / 34877.0);
assert_eq!(orderbook.bids[4].quantity_quote, 61292.0);
assert_eq!(orderbook.bids[4].quantity_contract.unwrap(), 61292.0);
assert_eq!(orderbook.asks[0].price, 34880.5);
assert_eq!(orderbook.asks[0].quantity_base, 506.0 / 34880.5);
assert_eq!(orderbook.asks[0].quantity_quote, 506.0);
assert_eq!(orderbook.asks[0].quantity_contract.unwrap(), 506.0);
assert_eq!(orderbook.asks[4].price, 34882.5);
assert_eq!(orderbook.asks[4].quantity_base, 135651.0 / 34882.5);
assert_eq!(orderbook.asks[4].quantity_quote, 135651.0);
assert_eq!(orderbook.asks[4].quantity_contract.unwrap(), 135651.0);
}
#[test]
fn inverse_swap_update() {
let raw_msg = r#"{"action":"update","data":[{"asks":[["34641.5","101367"],["34642","25822"]],"bids":[["34637","510"]],"instrument_id":"btcusd","timestamp":"1622431636806"}],"table":"swap/depth"}"#;
let orderbook =
&parse_l2(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap()[0];
assert_eq!(orderbook.asks.len(), 2);
assert_eq!(orderbook.bids.len(), 1);
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!(
1622431636806,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg)
.unwrap()
.unwrap()
);
assert_eq!(orderbook.timestamp, 1622431636806);
assert_eq!(orderbook.bids[0].price, 34637.0);
assert_eq!(orderbook.bids[0].quantity_base, 510.0 / 34637.0);
assert_eq!(orderbook.bids[0].quantity_quote, 510.0);
assert_eq!(orderbook.bids[0].quantity_contract.unwrap(), 510.0);
assert_eq!(orderbook.asks[0].price, 34641.5);
assert_eq!(orderbook.asks[0].quantity_base, 101367.0 / 34641.5);
assert_eq!(orderbook.asks[0].quantity_quote, 101367.0);
assert_eq!(orderbook.asks[0].quantity_contract.unwrap(), 101367.0);
assert_eq!(orderbook.asks[1].price, 34642.0);
assert_eq!(orderbook.asks[1].quantity_base, 25822.0 / 34642.0);
assert_eq!(orderbook.asks[1].quantity_quote, 25822.0);
assert_eq!(orderbook.asks[1].quantity_contract.unwrap(), 25822.0);
}
}
#[cfg(test)]
mod l2_topk {
use super::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 linear_swap() {
let raw_msg = r#"{"data":[{"asks":[["371.18","307"],["371.19","171"],["371.20","111"],["371.21","454"],["371.22","414"]],"bids":[["370.87","1479"],["370.86","326"],["370.85","49"],["370.84","752"],["370.83","1415"]],"instrument_id":"cmt_bchusdt","timestamp":"1648785601210"}],"table":"swap/depth5"}"#;
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,
"BCH/USDT".to_string(),
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap(),
orderbook,
raw_msg,
);
assert_eq!(
"cmt_bchusdt",
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()
);
assert_eq!(
1648785601210,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
assert_eq!(orderbook.timestamp, 1648785601210);
assert_eq!(orderbook.bids[0].price, 370.87);
assert_eq!(orderbook.bids[0].quantity_base, round(0.01 * 1479.0));
assert_eq!(orderbook.bids[0].quantity_quote, 0.01 * 1479.0 * 370.87);
assert_eq!(orderbook.bids[0].quantity_contract.unwrap(), 1479.0);
assert_eq!(orderbook.bids[4].price, 370.83);
assert_eq!(orderbook.bids[4].quantity_base, 0.01 * 1415.0);
assert_eq!(orderbook.bids[4].quantity_quote, 0.01 * 1415.0 * 370.83);
assert_eq!(orderbook.bids[4].quantity_contract.unwrap(), 1415.0);
assert_eq!(orderbook.asks[0].price, 371.18);
assert_eq!(orderbook.asks[0].quantity_base, round(0.01 * 307.0));
assert_eq!(orderbook.asks[0].quantity_quote, round(0.01 * 307.0 * 371.18));
assert_eq!(orderbook.asks[0].quantity_contract.unwrap(), 307.0);
assert_eq!(orderbook.asks[4].price, 371.22);
assert_eq!(orderbook.asks[4].quantity_base, 0.01 * 414.0);
assert_eq!(orderbook.asks[4].quantity_quote, 0.01 * 414.0 * 371.22);
assert_eq!(orderbook.asks[4].quantity_contract.unwrap(), 414.0);
}
}
#[cfg(test)]
mod candlestick {
use super::super::EXCHANGE_NAME;
use crypto_market_type::MarketType;
use crypto_msg_parser::{extract_symbol, extract_timestamp, parse_candlestick, round};
#[test]
fn inverse_swap() {
let raw_msg = r#"{"data":{"candle":["1646092800000","43156.0","43157.5","43156.0","43157.5","1547","0.035845449809"],"instrument_id":"btcusd"},"table":"swap/candle60s"}"#;
assert_eq!(
"btcusd",
extract_symbol(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg).unwrap()
);
assert_eq!(
1646092800000,
extract_timestamp(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg)
.unwrap()
.unwrap()
);
let arr =
parse_candlestick(EXCHANGE_NAME, MarketType::InverseSwap, raw_msg, None).unwrap();
assert_eq!(1, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("btcusd", candlestick_msg.symbol);
assert_eq!("BTC/USD", candlestick_msg.pair);
assert_eq!(1646092800000, candlestick_msg.timestamp);
assert_eq!(1646092740000, candlestick_msg.begin_time);
assert_eq!("60s", candlestick_msg.period);
assert_eq!(43156.0, candlestick_msg.open);
assert_eq!(43157.5, candlestick_msg.high);
assert_eq!(43156.0, candlestick_msg.low);
assert_eq!(43157.5, candlestick_msg.close);
assert_eq!(0.035845449809, candlestick_msg.volume);
assert_eq!(Some(1547.0), candlestick_msg.quote_volume);
}
#[test]
fn linear_swap() {
let raw_msg = r#"{"data":{"candle":["1648801800000","45298.5","45298.5","45274.0","45274.0","1273","57633.802000000000"],"instrument_id":"cmt_btcusdt"},"table":"swap/candle60s"}"#;
assert_eq!(
"cmt_btcusdt",
extract_symbol(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap()
);
assert_eq!(
1648801800000,
extract_timestamp(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg).unwrap().unwrap()
);
let arr =
parse_candlestick(EXCHANGE_NAME, MarketType::LinearSwap, raw_msg, None).unwrap();
assert_eq!(1, arr.len());
let candlestick_msg = &arr[0];
assert_eq!("cmt_btcusdt", candlestick_msg.symbol);
assert_eq!("BTC/USDT", candlestick_msg.pair);
assert_eq!(1648801800000, candlestick_msg.timestamp);
assert_eq!(1648801740000, candlestick_msg.begin_time);
assert_eq!("60s", candlestick_msg.period);
assert_eq!(45298.5, candlestick_msg.open);
assert_eq!(45298.5, candlestick_msg.high);
assert_eq!(45274.0, candlestick_msg.low);
assert_eq!(45274.0, candlestick_msg.close);
assert_eq!(1.273, round(candlestick_msg.volume));
assert_eq!(Some(57633.802), candlestick_msg.quote_volume);
}
}
}