tse_client/config.rs
1//! Runtime configuration and per-call settings.
2//!
3//! The original JS exposed these as mutable module-level globals with
4//! validating getters/setters. In Rust we use an owned `Config` struct on the
5//! client instead of `static mut`, which is both safer and avoids cross-call
6//! state bleed.
7
8use crate::group::Period;
9
10/// Tunable client configuration (the JS `*_UPDATE_*` globals and URLs).
11#[derive(Debug, Clone)]
12pub struct Config {
13 pub api_url: String,
14 pub update_interval: i64,
15 pub prices_update_chunk: usize,
16 pub prices_update_chunk_delay: u64,
17 pub prices_update_retry_count: u32,
18 pub prices_update_retry_delay: u64,
19
20 pub intraday_update_chunk_delay: u64,
21 pub intraday_update_chunk_max_wait: u64,
22 pub intraday_update_retry_count: u32,
23 pub intraday_update_retry_delay: u64,
24 pub intraday_update_servers: Vec<i32>,
25}
26
27impl Default for Config {
28 fn default() -> Self {
29 Config {
30 api_url: crate::request::DEFAULT_API_URL.to_string(),
31 update_interval: 1,
32 prices_update_chunk: 50,
33 prices_update_chunk_delay: 300,
34 prices_update_retry_count: 3,
35 prices_update_retry_delay: 1000,
36
37 intraday_update_chunk_delay: 100,
38 intraday_update_chunk_max_wait: 60_000,
39 intraday_update_retry_count: 3,
40 intraday_update_retry_delay: 1000,
41 intraday_update_servers: vec![-1, 0],
42 }
43 }
44}
45
46/// Per-call settings for `get_prices` (JS `defaultSettings`).
47#[derive(Debug, Clone)]
48pub struct PriceSettings {
49 /// Column indices to include in the output.
50 ///
51 /// Maps to `columnList` indices. Default: `[0, 2, 3, 4, 5, 6, 7, 8, 9]`
52 pub columns: Vec<usize>,
53
54 /// Price adjustment mode applied to returned data.
55 ///
56 /// - `0`: No adjustment (`بدون تعدیل`)
57 /// - `1`: Capital increase + dividends (`افزایش سرمایه + سود نقدی`)
58 /// - `2`: Capital increase only (`افزایش سرمایه`)
59 pub adjust_prices: u8,
60
61 /// If `true`, an `adjust_info` payload is appended to each `ClosingPrice`
62 /// containing all events needed to manually re-apply price adjustment.
63 ///
64 /// Default: `false`
65 pub get_adjust_info: bool,
66
67 /// If `true`, returns only the `adjust_info` payload without any
68 /// `ClosingPrice` data. Implies `get_adjust_info`.
69 ///
70 /// Default: `false`
71 pub get_adjust_info_only: bool,
72
73 /// If `true`, rows with zero trades are included in the output.
74 ///
75 /// Default: `false`
76 pub days_without_trade: bool,
77
78 /// Start date for price data in `YYYYMMDD` format (e.g., `"20230101"`).
79 /// Only prices with dates greater than this value will be included.
80 ///
81 /// Min: `"20010321"`. Default: `"20010321"`
82 pub start_date: String,
83
84 /// End date for price data in `YYYYMMDD` format (e.g., `"20231231"`).
85 /// Only prices with dates less than or equal to this value will be included.
86 /// If empty, no end date filtering is applied.
87 ///
88 /// `start_date` should be less than or equal to `end_date` when both are specified.
89 pub end_date: String,
90
91 /// If `true`, data for similar renamed symbols is merged into a single series.
92 ///
93 /// Default: `true`
94 pub merge_similar_symbols: bool,
95
96 /// If `true`, downloaded data is persisted to the local cache directory.
97 ///
98 /// Default: `true`
99 pub cache: bool,
100
101 /// If `true`, each symbol's result is returned as a CSV string instead
102 /// of a structured `ClosingPrice` object.
103 ///
104 /// Default: `false`
105 pub csv: bool,
106
107 /// If `true`, a header row is prepended to each CSV result.
108 /// Has no effect when `csv` is `false`.
109 ///
110 /// Default: `true`
111 pub csv_headers: bool,
112
113 /// Cell delimiter character used when generating CSV results.
114 /// Has no effect when `csv` is `false`.
115 ///
116 /// Default: `","`
117 pub csv_delimiter: String,
118
119 /// Resampling timeframe for the returned rows. Daily (default) keeps the
120 /// rows as-is; Weekly/Monthly aggregate them using the Jalali calendar.
121 pub period: Period,
122}
123
124impl Default for PriceSettings {
125 fn default() -> Self {
126 PriceSettings {
127 columns: vec![0, 2, 3, 4, 5, 6, 7, 8, 9],
128 adjust_prices: 0,
129 get_adjust_info: false,
130 get_adjust_info_only: false,
131 days_without_trade: false,
132 start_date: "20010321".to_string(),
133 end_date: String::new(),
134 merge_similar_symbols: true,
135 cache: true,
136 csv: false,
137 csv_headers: true,
138 csv_delimiter: ",".to_string(),
139 period: Period::Daily,
140 }
141 }
142}
143
144/// Per-call settings for `get_intraday` (JS `itdDefaultSettings`).
145#[derive(Debug, Clone)]
146pub struct IntradaySettings {
147 pub start_date: String,
148 pub end_date: String,
149 pub cache: bool,
150 pub gzip: bool,
151 pub re_update_no_trades: bool,
152 pub update_only: bool,
153 pub chunk_delay: u64,
154 pub chunk_max_wait: u64,
155 pub retry_count: u32,
156 pub retry_delay: u64,
157 pub servers: Vec<i32>,
158}
159
160impl Default for IntradaySettings {
161 fn default() -> Self {
162 IntradaySettings {
163 start_date: "20010321".to_string(),
164 end_date: String::new(),
165 cache: true,
166 gzip: true,
167 re_update_no_trades: false,
168 update_only: false,
169 chunk_delay: 100,
170 chunk_max_wait: 60_000,
171 retry_count: 3,
172 retry_delay: 1000,
173 servers: vec![-1, 0],
174 }
175 }
176}
177
178pub const SYMBOL_RENAME_STRING: &str = "-ق";
179pub const TRADING_SESSION_END_HOUR: u8 = 16;