I’ve been experimenting with Rust for processing larger time-series datasets and I’m trying to figure out the most sensible approach once the files stop being small.
The data itself is pretty simple:
timestamp,symbol,price,volume
1720000000,BTCUSDT,61250.4,0.82
1720000060,BTCUSDT,61271.1,1.14
Some of the historical market data I’m working with comes from different sources, including exports from BYDFi. After cleaning it, the files can easily grow to several million rows.
My first thought was to use the csv crate and process each record one by one instead of loading the whole dataset into memory:
use csv::Reader;
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let mut reader = Reader::from_path("market_data.csv")?;
for result in reader.records() {
let record = result?;
// process each row
}
Ok(())
}
That seems straightforward when I only need to calculate something simple.
Where I’m getting a little stuck is rolling calculations. For example, if I want to calculate returns, a moving average, or volatility over the previous 100 or 1,000 observations, I obviously need to keep some previous values around.
Would a VecDeque with a fixed maximum size be a reasonable approach here?
I’ve also looked at Polars, which seems much more convenient for this type of analysis, but I’m wondering whether using a dataframe library defeats some of the reason for doing this in Rust in the first place.
For datasets with a few million rows, would you generally:
- stream the CSV and maintain a rolling buffer;
- load the data with Polars and use its built-in operations; or
- use another approach entirely?
I’m coming from more of a Python/data-analysis background, so I’m interested in what would be considered the more idiomatic Rust approach.
Thanks!