From f0e239f22fec401464fa3ee211b368f7251a6954 Mon Sep 17 00:00:00 2001 From: zjp Date: Tue, 24 Sep 2024 16:55:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=B8=8D=E4=BD=BF=E7=94=A8=20last=5Fval?= =?UTF-8?q?ue=EF=BC=8C=E8=80=8C=E6=98=AF=E5=9F=BA=E4=BA=8E=20groupArray=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=9C=80=E6=96=B0=20factor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 day 和 east 的子命令参数上增加 --keep-factor,来保留 factor.csv。 close https://github.com/zjp-CN/rustdx/issues/33 --- assets/factor.sql | 16 +++++++++++ rustdx-cmd/src/cmd/day.rs | 4 +++ rustdx-cmd/src/cmd/east.rs | 8 +++++- rustdx-cmd/src/io.rs | 59 ++++++++++++++++++++++++-------------- rustdx-cmd/src/main.rs | 4 ++- 5 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 assets/factor.sql diff --git a/assets/factor.sql b/assets/factor.sql new file mode 100644 index 0000000..a4cb85f --- /dev/null +++ b/assets/factor.sql @@ -0,0 +1,16 @@ +WITH + df AS ( + SELECT + code, + arrayLast( + x->true, + arraySort(x->x.1, groupArray(( + date, close, factor + ))) + ) AS t + FROM + rustdx.factor + GROUP BY + code + ) +SELECT code, t.1 AS date, t.2 AS close, t.3 AS factor FROM df; diff --git a/rustdx-cmd/src/cmd/day.rs b/rustdx-cmd/src/cmd/day.rs index 5dc8abf..2735580 100644 --- a/rustdx-cmd/src/cmd/day.rs +++ b/rustdx-cmd/src/cmd/day.rs @@ -20,6 +20,10 @@ pub struct DayCmd { #[argh(switch, short = 'k', long = "keep-csv")] pub keep_csv: bool, + /// 可选。指定时,表示保存 factor.csv 文件。 + #[argh(switch)] + pub keep_factor: bool, + /// 可选。指定复权数据(csv 文件路径)。如果没有指定这个参数,则不会计算复权。 #[argh(option, short = 'g')] pub gbbq: Option, diff --git a/rustdx-cmd/src/cmd/east.rs b/rustdx-cmd/src/cmd/east.rs index c0ad55f..527e331 100644 --- a/rustdx-cmd/src/cmd/east.rs +++ b/rustdx-cmd/src/cmd/east.rs @@ -20,6 +20,10 @@ pub struct EastCmd { #[argh(option, short = 'i')] pub ignore: Vec, + /// 可选。指定时,表示保存 factor.csv 文件。 + #[argh(switch)] + pub keep_factor: bool, + /// 股票总个数,默认 6000。 #[argh(option, short = 'n', default = "6000")] pub n: u16, @@ -70,7 +74,8 @@ impl EastCmd { } fn _run_previous(&self, mut json: EastMarket) -> Result<()> { - let previous = crate::io::previous_csv_table(&self.previous, &self.table)?; + let previous = + crate::io::previous_csv_table(&self.previous, &self.table, self.keep_factor)?; let file = std::fs::File::create(&self.output)?; let mut wrt = csv::Writer::from_writer(file); for row in &mut json.data.diff { @@ -101,6 +106,7 @@ impl EastCmd { ); } } else { + warn!("{} 无前日收盘价数据", row.code); row.factor = c as f64 / p as f64; } wrt.serialize(row)?; diff --git a/rustdx-cmd/src/io.rs b/rustdx-cmd/src/io.rs index 539a0e3..a0b6b48 100644 --- a/rustdx-cmd/src/io.rs +++ b/rustdx-cmd/src/io.rs @@ -87,7 +87,7 @@ pub fn run_csv_fq_previous(cmd: &DayCmd) -> Result<()> { let gbbq = Gbbq::filter_hashmap(Gbbq::iter(&mut bytes[4..])); // 前收 - let previous = previous_csv_table(&cmd.previous, &cmd.table)?; + let previous = previous_csv_table(&cmd.previous, &cmd.table, cmd.keep_factor)?; // 股票列表 let hm = cmd.stocklist(); @@ -234,12 +234,16 @@ fn test_insert_clickhouse() -> Result<()> { type Previous = Result>; -pub fn previous_csv_table(path: &Option, table: &str) -> Previous { +pub fn previous_csv_table( + path: &Option, + table: &str, + keep_factor: bool, +) -> Previous { if let Some(Some(path)) = path.as_ref().map(|p| p.to_str()) { if path == "clickhouse" { - clickhouse_factor_csv(table) + clickhouse_factor_csv(table, keep_factor) } else { - previous_csv(path) + previous_csv(path, keep_factor) } } else { Err(anyhow!("请检查 gbbq 路径")) @@ -247,36 +251,47 @@ pub fn previous_csv_table(path: &Option, table: &str) -> Pre } /// 读取前收盘价(前 factor )数据 -pub fn previous_csv(p: impl AsRef) -> Previous { +pub fn previous_csv(p: impl AsRef, keep_factor: bool) -> Previous { let path = p.as_ref(); let prev = csv::Reader::from_reader(File::open(path)?) .deserialize::() .filter_map(|f| f.ok()) .map(|f| (f.code.parse().unwrap(), f)) .collect(); - fs::remove_file(path)?; + if !keep_factor { + fs::remove_file(path)?; + } Ok(prev) } /// 获取当前最新 factor -fn clickhouse_factor_csv(table: &str) -> Previous { - let args = [ - "--query", - &format!( - "SELECT - yesterday() AS date, - code, - last_value(close) AS close, - last_value(factor) AS factor - FROM {table} - GROUP BY code - INTO OUTFILE 'factor.csv' - FORMAT CSVWithNames;" - ), - ]; +fn clickhouse_factor_csv(table: &str, keep_factor: bool) -> Previous { + let query = format!( + "\ +WITH + df AS ( + SELECT + code, + arrayLast( + x->true, + arraySort(x->x.1, groupArray(( + date, close, factor + ))) + ) AS t + FROM + {table} + GROUP BY + code + ) +SELECT code, t.1 AS date, t.2 AS close, t.3 AS factor FROM df +INTO OUTFILE 'factor.csv' +FORMAT CSVWithNames;" + ); + let args = ["--query", &query]; let output = Command::new("clickhouse-client").args(args).output()?; + info!("clickhouse-client --query {query:?}"); check_output(output); - previous_csv("factor.csv") + previous_csv("factor.csv", keep_factor) } /// TODO: 与数据库有关的,把库名、表名可配置 diff --git a/rustdx-cmd/src/main.rs b/rustdx-cmd/src/main.rs index 2856ffe..b4e0577 100644 --- a/rustdx-cmd/src/main.rs +++ b/rustdx-cmd/src/main.rs @@ -7,7 +7,9 @@ extern crate log; use eyre::Result; fn main() -> Result<()> { - env_logger::init(); + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .init(); let cmd: cmd::TopLevel = argh::from_env(); cmd.match_subcmd() }