tdx_rs/tdx_model/builder/
day_line_builder.rs1use std::{
2 fs::File,
3 io::{Read, Seek, SeekFrom},
4 path::Path,
5};
6
7use byteorder::ByteOrder;
8
9use crate::tdx_model::{data::DailyData, DayLine};
10
11pub const DAY_SIZE: usize = 32;
13
14#[derive(Debug)]
15pub struct DayLineBuilder {
16 pub file: File,
17 pub max_days: u64,
18}
19
20impl DayLineBuilder {
21 pub fn from_path<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
22 let file = File::open(path.as_ref())?;
23 let max_days = std::fs::metadata(path.as_ref())?.len() / (DAY_SIZE as u64);
24
25 Ok(Self { file, max_days })
26 }
27
28 pub fn query_days(mut self, days: u64) -> Self {
29 if self.max_days > days {
30 self.max_days = days;
32 }
33
34 let pos_offset = (self.max_days * DAY_SIZE as u64) as i64;
35 self.file.seek(SeekFrom::End(0 - pos_offset)).unwrap();
36
37 self
38 }
39
40 pub fn build(mut self) -> DayLine {
41 let mut buffer = [0u8; DAY_SIZE];
42 let mut day_line = Vec::with_capacity(self.max_days as usize);
43
44 for _ in 0..self.max_days {
45 self.file.read_exact(buffer.as_mut()).unwrap();
46 let date = byteorder::LE::read_u32(&buffer[0..4]);
47 let open = byteorder::LE::read_u32(&buffer[4..8]) as f64 / 100f64;
48 let high = byteorder::LE::read_u32(&buffer[8..12]) as f64 / 100f64;
49 let low = byteorder::LE::read_u32(&buffer[12..16]) as f64 / 100f64;
50 let close = byteorder::LE::read_u32(&buffer[16..20]) as f64 / 100f64;
51 let daily_data = DailyData::new(date, open, high, low, close);
54 day_line.push(daily_data);
55 }
56
57 DayLine::new(day_line)
58 }
59}
60
61#[test]
62fn builder_test() -> anyhow::Result<()> {
63 let builder = DayLineBuilder::from_path("../data/shlday/sh600000.day")?.query_days(400);
64 let day_line = builder.build();
65 dbg!(day_line.data.len());
66 Ok(())
67}