1use std::time::Duration;
4
5use anyhow::Result;
6use serde::Serialize;
7use tabled::Tabled;
8
9use crate::common::{connect_gateway, format_symbol, parse_symbol};
10use crate::output::OutputFormat;
11use futu_qot::types::SubType;
12
13#[derive(Tabled)]
14struct OrderBookRow {
15 #[tabled(rename = "Side")]
16 side: String,
17 #[tabled(rename = "Level")]
18 level: i32,
19 #[tabled(rename = "Price")]
20 price: String,
21 #[tabled(rename = "Volume")]
22 volume: String,
23 #[tabled(rename = "Orders")]
24 orders: i32,
25}
26
27#[derive(Serialize)]
28struct OrderBookJson {
29 symbol: String,
30 bids: Vec<Level>,
31 asks: Vec<Level>,
32}
33
34#[derive(Serialize)]
35struct Level {
36 price: f64,
37 volume: i64,
38 orders: i32,
39}
40
41pub async fn run(gateway: &str, symbol: &str, depth: i32, format: OutputFormat) -> Result<()> {
42 let sec = parse_symbol(symbol)?;
43 let (client, _push_rx) = connect_gateway(gateway, "futucli-orderbook").await?;
44
45 futu_qot::sub::subscribe(
47 &client,
48 std::slice::from_ref(&sec),
49 &[SubType::OrderBook],
50 true,
51 true,
52 )
53 .await?;
54 tokio::time::sleep(Duration::from_millis(300)).await;
55
56 let ob = futu_qot::order_book::get_order_book(&client, &sec, depth).await?;
57
58 let mut rows = Vec::new();
60 for (i, a) in ob.ask_list.iter().enumerate().rev() {
61 rows.push(OrderBookRow {
62 side: "ASK".to_string(),
63 level: (i + 1) as i32,
64 price: format!("{:.3}", a.price),
65 volume: a.volume.to_string(),
66 orders: a.order_count,
67 });
68 }
69 for (i, b) in ob.bid_list.iter().enumerate() {
70 rows.push(OrderBookRow {
71 side: "BID".to_string(),
72 level: (i + 1) as i32,
73 price: format!("{:.3}", b.price),
74 volume: b.volume.to_string(),
75 orders: b.order_count,
76 });
77 }
78
79 let json = OrderBookJson {
80 symbol: format_symbol(&ob.security),
81 bids: ob
82 .bid_list
83 .iter()
84 .map(|e| Level {
85 price: e.price,
86 volume: e.volume,
87 orders: e.order_count,
88 })
89 .collect(),
90 asks: ob
91 .ask_list
92 .iter()
93 .map(|e| Level {
94 price: e.price,
95 volume: e.volume,
96 orders: e.order_count,
97 })
98 .collect(),
99 };
100
101 format.print_rows(&rows, std::slice::from_ref(&json))?;
102 Ok(())
103}