1use crate::error::{Error, Result};
4use crate::util::clean_fa;
5
6pub const COLS: [&str; 15] = [
8 "date",
9 "dateshamsi",
10 "open",
11 "high",
12 "low",
13 "last",
14 "close",
15 "vol",
16 "count",
17 "value",
18 "yesterday",
19 "symbol",
20 "name",
21 "namelatin",
22 "companycode",
23];
24
25pub const COLS_FA: [&str; 15] = [
27 "تاریخ میلادی",
28 "تاریخ شمسی",
29 "اولین قیمت",
30 "بیشترین قیمت",
31 "کمترین قیمت",
32 "آخرین قیمت",
33 "قیمت پایانی",
34 "حجم معاملات",
35 "تعداد معاملات",
36 "ارزش معاملات",
37 "قیمت پایانی دیروز",
38 "نماد",
39 "نام",
40 "نام لاتین",
41 "کد شرکت",
42];
43
44#[derive(Debug, Clone, PartialEq, Eq)]
48pub struct ClosingPrice {
49 pub ins_code: String, pub deven: String, pub pclosing: String, pub pdr_cot_val: String, pub ztot_tran: String, pub qtot_tran5j: String, pub qtot_cap: String, pub price_min: String, pub price_max: String, pub price_yesterday: String, pub price_first: String, }
61
62impl ClosingPrice {
63 pub fn parse(row: &str) -> Result<Self> {
65 let f: Vec<&str> = row.split(',').collect();
66 if f.len() != 11 {
67 return Err(Error::InvalidData("Invalid ClosingPrice data!".into()));
68 }
69 Ok(ClosingPrice {
70 ins_code: f[0].to_string(),
71 deven: f[1].to_string(),
72 pclosing: f[2].to_string(),
73 pdr_cot_val: f[3].to_string(),
74 ztot_tran: f[4].to_string(),
75 qtot_tran5j: f[5].to_string(),
76 qtot_cap: f[6].to_string(),
77 price_min: f[7].to_string(),
78 price_max: f[8].to_string(),
79 price_yesterday: f[9].to_string(),
80 price_first: f[10].to_string(),
81 })
82 }
83
84 pub fn to_csv_row(&self) -> String {
86 [
87 &self.ins_code,
88 &self.deven,
89 &self.pclosing,
90 &self.pdr_cot_val,
91 &self.ztot_tran,
92 &self.qtot_tran5j,
93 &self.qtot_cap,
94 &self.price_min,
95 &self.price_max,
96 &self.price_yesterday,
97 &self.price_first,
98 ]
99 .map(|s| s.as_str())
100 .join(",")
101 }
102}
103
104#[derive(Debug, Clone)]
106pub struct Column {
107 pub name: &'static str,
108 pub fname: &'static str,
109 pub header: String,
110}
111
112impl Column {
113 pub fn new(index: usize, header: Option<String>) -> Result<Self> {
115 if index >= COLS.len() {
116 return Err(Error::InvalidData("Invalid Column data!".into()));
117 }
118 let name = COLS[index];
119 let header = header
120 .filter(|h| !h.is_empty())
121 .unwrap_or_else(|| name.to_string());
122 Ok(Column {
123 name,
124 fname: COLS_FA[index],
125 header,
126 })
127 }
128}
129
130#[derive(Debug, Clone)]
132pub struct Instrument {
133 pub ins_code: String,
134 pub instrument_id: String,
135 pub latin_symbol: String,
136 pub latin_name: String,
137 pub company_code: String,
138 pub symbol: String,
139 pub name: String,
140 pub cisin: String,
141 pub deven: String,
142 pub flow: String,
143 pub lsoc30: String,
144 pub cgds_val: String,
145 pub cgr_val_cot: String,
146 pub ymar_nsc: String,
147 pub ccom_val: String,
148 pub csec_val: String,
149 pub cso_sec_val: String,
150 pub yval: String,
151 pub symbol_original: Option<String>,
152}
153
154impl Instrument {
155 pub fn parse(row: &str) -> Result<Self> {
156 let f: Vec<&str> = row.split(',').collect();
157 if f.len() != 18 && f.len() != 19 {
158 return Err(Error::InvalidData("Invalid Instrument data!".into()));
159 }
160 Ok(Instrument {
161 ins_code: f[0].to_string(),
162 instrument_id: f[1].to_string(),
163 latin_symbol: f[2].to_string(),
164 latin_name: f[3].to_string(),
165 company_code: f[4].to_string(),
166 symbol: clean_fa(f[5]).trim().to_string(),
167 name: f[6].to_string(),
168 cisin: f[7].to_string(),
169 deven: f[8].to_string(),
170 flow: f[9].to_string(),
171 lsoc30: f[10].to_string(),
172 cgds_val: f[11].to_string(),
173 cgr_val_cot: f[12].to_string(),
174 ymar_nsc: f[13].to_string(),
175 ccom_val: f[14].to_string(),
176 csec_val: f[15].to_string(),
177 cso_sec_val: f[16].to_string(),
178 yval: f[17].to_string(),
179 symbol_original: f
180 .get(18)
181 .filter(|s| !s.is_empty())
182 .map(|s| clean_fa(s).trim().to_string()),
183 })
184 }
185}
186
187#[derive(Debug, Clone)]
189pub struct InstrumentItd {
190 pub ins_code: String,
191 pub lval30: String,
192 pub lval18afc: String,
193 pub flow_title: String,
194 pub cgr_val_cot_title: String,
195 pub flow: String,
196 pub cgr_val_cot: String,
197 pub cisin: String,
198 pub instrument_id: String,
199 pub ztitad: String,
200 pub base_vol: String,
201}
202
203impl InstrumentItd {
204 pub fn parse(row: &str) -> Result<Self> {
205 let f: Vec<&str> = row.split(',').collect();
206 if f.len() != 11 {
207 return Err(Error::InvalidData("Invalid InstrumentITD data!".into()));
208 }
209 Ok(InstrumentItd {
210 ins_code: f[0].to_string(),
211 lval30: clean_fa(f[1]),
212 lval18afc: clean_fa(f[2]),
213 flow_title: clean_fa(f[3]),
214 cgr_val_cot_title: clean_fa(f[4]),
215 flow: f[5].to_string(),
216 cgr_val_cot: f[6].to_string(),
217 cisin: f[7].to_string(),
218 instrument_id: f[8].to_string(),
219 ztitad: f[9].to_string(),
220 base_vol: f[10].to_string(),
221 })
222 }
223}
224
225#[derive(Debug, Clone)]
227pub struct Share {
228 pub idn: String,
229 pub ins_code: String,
230 pub deven: String,
231 pub number_of_share_new: i64,
232 pub number_of_share_old: i64,
233}
234
235impl Share {
236 pub fn parse(row: &str) -> Result<Self> {
237 let f: Vec<&str> = row.split(',').collect();
238 if f.len() != 5 {
239 return Err(Error::InvalidData("Invalid Share data!".into()));
240 }
241 Ok(Share {
242 idn: f[0].to_string(),
243 ins_code: f[1].to_string(),
244 deven: f[2].to_string(),
245 number_of_share_new: f[3].trim().parse().unwrap_or(0),
246 number_of_share_old: f[4].trim().parse().unwrap_or(0),
247 })
248 }
249}
250
251pub fn itd_group_cols() -> Vec<(&'static str, Vec<&'static str>)> {
253 vec![
254 (
255 "price",
256 vec![
257 "time",
258 "last",
259 "close",
260 "open",
261 "high",
262 "low",
263 "count",
264 "volume",
265 "value",
266 "discarded",
267 ],
268 ),
269 (
270 "order",
271 vec![
272 "time", "row", "askcount", "askvol", "askprice", "bidprice", "bidvol", "bidcount",
273 ],
274 ),
275 (
276 "trade",
277 vec!["time", "count", "volume", "price", "discarded"],
278 ),
279 (
280 "client",
281 vec![
282 "pbvol", "pbcount", "pbval", "pbprice", "pbvolpot", "psvol", "pscount", "psval",
283 "psprice", "psvolpot", "lbvol", "lbcount", "lbval", "lbprice", "lbvolpot", "lsvol",
284 "lscount", "lsval", "lsprice", "lsvolpot", "lpchg",
285 ],
286 ),
287 ("misc", vec!["basevol", "flow", "daymin", "daymax", "state"]),
288 (
289 "shareholder",
290 vec![
291 "shares",
292 "sharespot",
293 "change",
294 "companycode",
295 "companyname",
296 ],
297 ),
298 ]
299}