Skip to main content

futucli/cmd/
ticker.rs

1//! `futucli ticker` — 获取逐笔成交
2
3use std::time::Duration;
4
5use anyhow::Result;
6use serde::Serialize;
7use tabled::Tabled;
8
9use crate::common::{connect_gateway, parse_symbol};
10use crate::output::OutputFormat;
11use futu_qot::types::SubType;
12
13#[derive(Tabled)]
14struct TickerRow {
15    #[tabled(rename = "Time")]
16    time: String,
17    #[tabled(rename = "Seq")]
18    sequence: String,
19    #[tabled(rename = "Price")]
20    price: String,
21    #[tabled(rename = "Volume")]
22    volume: String,
23    #[tabled(rename = "Dir")]
24    dir: String,
25    #[tabled(rename = "Turnover")]
26    turnover: String,
27}
28
29#[derive(Serialize)]
30struct TickerJson {
31    time: String,
32    sequence: i64,
33    price: f64,
34    volume: i64,
35    turnover: f64,
36    dir: i32,
37    ticker_type: Option<i32>,
38    timestamp: f64,
39}
40
41fn dir_label(d: i32) -> &'static str {
42    match d {
43        1 => "BUY",
44        2 => "SELL",
45        3 => "NEUTRAL",
46        _ => "?",
47    }
48}
49
50pub async fn run(gateway: &str, symbol: &str, count: i32, format: OutputFormat) -> Result<()> {
51    let sec = parse_symbol(symbol)?;
52    let (client, _push_rx) = connect_gateway(gateway, "futucli-ticker").await?;
53
54    futu_qot::sub::subscribe(
55        &client,
56        std::slice::from_ref(&sec),
57        &[SubType::Ticker],
58        true,
59        true,
60    )
61    .await?;
62    tokio::time::sleep(Duration::from_millis(300)).await;
63
64    let result = futu_qot::ticker::get_ticker(&client, &sec, count).await?;
65
66    let rows: Vec<TickerRow> = result
67        .ticker_list
68        .iter()
69        .map(|t| TickerRow {
70            time: t.time.clone(),
71            sequence: t.sequence.to_string(),
72            price: format!("{:.3}", t.price),
73            volume: t.volume.to_string(),
74            dir: dir_label(t.dir).to_string(),
75            turnover: format!("{:.0}", t.turnover),
76        })
77        .collect();
78
79    let jsons: Vec<TickerJson> = result
80        .ticker_list
81        .iter()
82        .map(|t| TickerJson {
83            time: t.time.clone(),
84            sequence: t.sequence,
85            price: t.price,
86            volume: t.volume,
87            turnover: t.turnover,
88            dir: t.dir,
89            ticker_type: t.ticker_type,
90            timestamp: t.timestamp,
91        })
92        .collect();
93
94    format.print_rows(&rows, &jsons)?;
95    Ok(())
96}