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
//! Candle utilities.

/// Calculates candle index starting from first timestamp.
#[inline(always)]
pub fn candle_index(ts: u64, first_ts: u64, interval: u64) -> usize {
    ((round_close(ts, interval) - first_ts) / interval) as usize
}

/// Calculates candle timestamp from first timestamp and index.
#[inline(always)]
pub fn candle_ts(first_ts: u64, index: usize, interval: u64) -> u64 {
    round_open(first_ts, interval) + (index as u64 * interval)
}

/// Rounds timestamp in milliseconds to a candle open time.
#[inline(always)]
pub fn round_open(t: u64, interval: u64) -> u64 {
    (((t as f64 / interval as f64).ceil() - 1.0) * interval as f64) as u64
}

/// Rounds timestamp in milliseconds to a candle close time.
#[inline(always)]
pub fn round_close(t: u64, interval: u64) -> u64 {
    ((t as f64 / interval as f64).ceil() * interval as f64) as u64
}

/// Calculates amount of candles during given time period.
/// Accepts rounded close start and end time of snapshot.
#[inline(always)]
pub fn candles_amount(first_ts: u64, max_ts: u64, interval: u64) -> u64 {
    ((max_ts - first_ts) as f64 / interval as f64).round() as u64 + 1
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_candle_index() {
        let first_ts = 1576852827000;
        let interval = 60 * 1000;
        let index = 42;
        let ts = first_ts + (interval * index as u64);
        assert_eq!(candle_index(ts, first_ts, interval), index);
    }
}