1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::;
use ;
/// Saves an orderbook snapshot to a CSV file.
///
/// Writes the orderbook state in a long-format CSV with one row per price level.
/// The output includes both bid and ask sides, sorted by level index where
/// level 0 represents the best bid/ask (top of book).
///
/// # Output Format
///
/// The CSV contains the following columns:
///
/// | Column | Type | Description |
/// |--------|------|-------------|
/// | `timestamp_ms` | `u64` | Unix timestamp in ms when the snapshot was taken |
/// | `symbol` | `String` | Trading pair symbol (e.g., "BTCUSDT") |
/// | `side` | `String` | Either "bid" or "ask" |
/// | `level` | `usize` | Depth level (0 = best price, 1 = second best, etc.) |
/// | `price` | `Decimal` | Price at this level |
/// | `size` | `Decimal` | Total quantity at this level |
///
/// # Arguments
///
/// * `ob` - Reference to the [`OrderbookDelta`] containing the current book state
/// * `path` - Destination file path. Parent directories must exist.
///
/// # Returns
///
/// * `Ok(())` - File was written successfully
/// * `Err(PersistError::Io)` - Failed to create file or write data
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
/// use atelier_data::orderbooks::{OrderbookDelta, io::write_csv};
///
/// let ob = OrderbookDelta::new("BTCUSDT");
/// // ... process some snapshots/deltas ...
///
/// write_csv(&ob, Path::new("./snapshots/btc_orderbook.csv"))?;
/// # Ok::<(), atelier_data::errors::PersistError>(())
/// ```
///
/// # Output Example
///
/// ```csv
/// timestamp_ms,symbol,side,level,price,size
/// 1706500000000,BTCUSDT,bid,0,42150.50,1.5000
/// 1706500000000,BTCUSDT,bid,1,42150.00,2.3000
/// 1706500000000,BTCUSDT,ask,0,42151.00,0.8000
/// 1706500000000,BTCUSDT,ask,1,42151.50,1.2000
/// ```