brokapi_tbank/map/
schedule.rs1use std::time::Instant;
4
5use brokapi_core::{Schedule, SessionInterval, SessionKind};
6use brokapi_tbank_protocol::v1 as pb;
7use prost_types::Timestamp;
8
9use crate::ids::{proto_to_nanos, stamps};
10
11fn push(
12 out: &mut Vec<SessionInterval>,
13 start: &Option<Timestamp>,
14 end: &Option<Timestamp>,
15 kind: SessionKind,
16) {
17 if let (Some(s), Some(e)) = (start, end)
18 && s.seconds != 0
19 && e.seconds != 0
20 && e.seconds >= s.seconds
21 {
22 out.push(SessionInterval {
23 start: proto_to_nanos(s),
24 end: proto_to_nanos(e),
25 kind,
26 });
27 }
28}
29
30pub fn schedule(exchange: &str, sched: &pb::TradingSchedule, now: Instant) -> Schedule {
32 let mut sessions = Vec::new();
33 for day in sched.days.iter().filter(|d| d.is_trading_day) {
34 push(
35 &mut sessions,
36 &day.premarket_start_time,
37 &day.premarket_end_time,
38 SessionKind::PreMarket,
39 );
40 push(
41 &mut sessions,
42 &day.opening_auction_start_time,
43 &day.opening_auction_end_time,
44 SessionKind::Auction,
45 );
46 push(
47 &mut sessions,
48 &day.start_time,
49 &day.end_time,
50 SessionKind::Main,
51 );
52 push(
53 &mut sessions,
54 &day.closing_auction_start_time,
55 &day.closing_auction_end_time,
56 SessionKind::Auction,
57 );
58 push(
59 &mut sessions,
60 &day.evening_start_time,
61 &day.evening_end_time,
62 SessionKind::PostMarket,
63 );
64 }
65 sessions.sort_by_key(|s| s.start);
66 Schedule {
67 exchange: exchange.to_string(),
68 sessions,
69 ts: stamps(now, None),
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 fn t(s: i64) -> Option<Timestamp> {
78 Some(Timestamp {
79 seconds: s,
80 nanos: 0,
81 })
82 }
83
84 #[test]
85 fn sessions_of_trading_days_sorted() {
86 let day = pb::TradingDay {
87 is_trading_day: true,
88 start_time: t(1_000),
89 end_time: t(2_000),
90 evening_start_time: t(3_000),
91 evening_end_time: t(4_000),
92 premarket_start_time: t(500),
93 premarket_end_time: t(900),
94 ..Default::default()
95 };
96 let off = pb::TradingDay {
97 is_trading_day: false,
98 start_time: t(10),
99 end_time: t(20),
100 ..Default::default()
101 };
102 let s = schedule(
103 "MOEX",
104 &pb::TradingSchedule {
105 exchange: "MOEX".into(),
106 days: vec![day, off],
107 },
108 Instant::now(),
109 );
110 let kinds: Vec<_> = s.sessions.iter().map(|x| x.kind).collect();
111 assert_eq!(
112 kinds,
113 vec![
114 SessionKind::PreMarket,
115 SessionKind::Main,
116 SessionKind::PostMarket
117 ]
118 );
119 }
120}