Spaces:
No application file
No application file
Kolesnikov Dmitry
commited on
Commit
·
b34a74f
1
Parent(s):
eaf6e74
feat: Sarima и VAR для третей лабораторки
Browse files- _lab3_input_tmp.csv +821 -0
- requirements.txt +12 -6
- src/lab3_functions.py +192 -0
- src/lab3_pipeline.py +272 -0
- src/lab4_functions.py +43 -0
- src/lab5_functions.py +48 -0
- src/streamlit_app.py +358 -2
- src/streamlit_lab3.py +50 -0
_lab3_input_tmp.csv
ADDED
|
@@ -0,0 +1,821 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
index,timestamp,DailyNewCases,ActiveCases,DailyNewDeaths
|
| 2 |
+
0,2020-02-15 00:00:00+03:00,0.0,0.0,0.0
|
| 3 |
+
1,2020-02-16 00:00:00+03:00,0.0,0.0,0.0
|
| 4 |
+
2,2020-02-17 00:00:00+03:00,0.0,0.0,0.0
|
| 5 |
+
3,2020-02-18 00:00:00+03:00,0.0,0.0,0.0
|
| 6 |
+
4,2020-02-19 00:00:00+03:00,0.0,0.0,0.0
|
| 7 |
+
5,2020-02-20 00:00:00+03:00,0.0,0.0,0.0
|
| 8 |
+
6,2020-02-21 00:00:00+03:00,0.0,0.0,0.0
|
| 9 |
+
7,2020-02-22 00:00:00+03:00,0.0,0.0,0.0
|
| 10 |
+
8,2020-02-23 00:00:00+03:00,0.0,0.0,0.0
|
| 11 |
+
9,2020-02-24 00:00:00+03:00,0.0,0.0,0.0
|
| 12 |
+
10,2020-02-25 00:00:00+03:00,0.0,0.0,0.0
|
| 13 |
+
11,2020-02-26 00:00:00+03:00,0.0,0.0,0.0
|
| 14 |
+
12,2020-02-27 00:00:00+03:00,0.0,0.0,0.0
|
| 15 |
+
13,2020-02-28 00:00:00+03:00,0.0,0.0,0.0
|
| 16 |
+
14,2020-02-29 00:00:00+03:00,0.0,0.0,0.0
|
| 17 |
+
15,2020-03-01 00:00:00+03:00,0.0,0.0,0.0
|
| 18 |
+
16,2020-03-02 00:00:00+03:00,1.0,1.0,0.0
|
| 19 |
+
17,2020-03-03 00:00:00+03:00,0.0,1.0,0.0
|
| 20 |
+
18,2020-03-04 00:00:00+03:00,0.0,1.0,0.0
|
| 21 |
+
19,2020-03-05 00:00:00+03:00,4.0,5.0,0.0
|
| 22 |
+
20,2020-03-06 00:00:00+03:00,6.0,11.0,0.0
|
| 23 |
+
21,2020-03-07 00:00:00+03:00,1.0,11.0,0.0
|
| 24 |
+
22,2020-03-08 00:00:00+03:00,3.0,14.0,0.0
|
| 25 |
+
23,2020-03-09 00:00:00+03:00,3.0,17.0,0.0
|
| 26 |
+
24,2020-03-10 00:00:00+03:00,0.0,17.0,0.0
|
| 27 |
+
25,2020-03-11 00:00:00+03:00,8.0,25.0,0.0
|
| 28 |
+
26,2020-03-12 00:00:00+03:00,6.0,31.0,0.0
|
| 29 |
+
27,2020-03-13 00:00:00+03:00,11.0,37.0,0.0
|
| 30 |
+
28,2020-03-14 00:00:00+03:00,14.0,51.0,0.0
|
| 31 |
+
29,2020-03-15 00:00:00+03:00,4.0,55.0,0.0
|
| 32 |
+
30,2020-03-16 00:00:00+03:00,30.0,85.0,0.0
|
| 33 |
+
31,2020-03-17 00:00:00+03:00,21.0,106.0,0.0
|
| 34 |
+
32,2020-03-18 00:00:00+03:00,33.0,139.0,0.0
|
| 35 |
+
33,2020-03-19 00:00:00+03:00,52.0,190.0,1.0
|
| 36 |
+
34,2020-03-20 00:00:00+03:00,54.0,240.0,0.0
|
| 37 |
+
35,2020-03-21 00:00:00+03:00,53.0,289.0,0.0
|
| 38 |
+
36,2020-03-22 00:00:00+03:00,61.0,350.0,0.0
|
| 39 |
+
37,2020-03-23 00:00:00+03:00,71.0,420.0,0.0
|
| 40 |
+
38,2020-03-24 00:00:00+03:00,57.0,472.0,0.0
|
| 41 |
+
39,2020-03-25 00:00:00+03:00,163.0,626.0,2.0
|
| 42 |
+
40,2020-03-26 00:00:00+03:00,182.0,799.0,0.0
|
| 43 |
+
41,2020-03-27 00:00:00+03:00,196.0,987.0,1.0
|
| 44 |
+
42,2020-03-28 00:00:00+03:00,228.0,1211.0,0.0
|
| 45 |
+
43,2020-03-29 00:00:00+03:00,270.0,1462.0,4.0
|
| 46 |
+
44,2020-03-30 00:00:00+03:00,302.0,1761.0,1.0
|
| 47 |
+
45,2020-03-31 00:00:00+03:00,501.0,2199.0,8.0
|
| 48 |
+
46,2020-04-01 00:00:00+03:00,440.0,2563.0,7.0
|
| 49 |
+
47,2020-04-02 00:00:00+03:00,771.0,3283.0,6.0
|
| 50 |
+
48,2020-04-03 00:00:00+03:00,601.0,3834.0,4.0
|
| 51 |
+
49,2020-04-04 00:00:00+03:00,582.0,4355.0,9.0
|
| 52 |
+
50,2020-04-05 00:00:00+03:00,658.0,4989.0,2.0
|
| 53 |
+
51,2020-04-06 00:00:00+03:00,954.0,5890.0,2.0
|
| 54 |
+
52,2020-04-07 00:00:00+03:00,1154.0,6945.0,11.0
|
| 55 |
+
53,2020-04-08 00:00:00+03:00,1175.0,8029.0,5.0
|
| 56 |
+
54,2020-04-09 00:00:00+03:00,1459.0,9357.0,13.0
|
| 57 |
+
55,2020-04-10 00:00:00+03:00,1786.0,11028.0,18.0
|
| 58 |
+
56,2020-04-11 00:00:00+03:00,1667.0,12433.0,12.0
|
| 59 |
+
57,2020-04-12 00:00:00+03:00,2186.0,14349.0,24.0
|
| 60 |
+
58,2020-04-13 00:00:00+03:00,2558.0,16710.0,18.0
|
| 61 |
+
59,2020-04-14 00:00:00+03:00,2774.0,19238.0,22.0
|
| 62 |
+
60,2020-04-15 00:00:00+03:00,3388.0,22306.0,28.0
|
| 63 |
+
61,2020-04-16 00:00:00+03:00,3448.0,25402.0,34.0
|
| 64 |
+
62,2020-04-17 00:00:00+03:00,4070.0,29145.0,41.0
|
| 65 |
+
63,2020-04-18 00:00:00+03:00,4785.0,33423.0,40.0
|
| 66 |
+
64,2020-04-19 00:00:00+03:00,6060.0,39201.0,48.0
|
| 67 |
+
65,2020-04-20 00:00:00+03:00,4268.0,43270.0,44.0
|
| 68 |
+
66,2020-04-21 00:00:00+03:00,5642.0,48434.0,51.0
|
| 69 |
+
67,2020-04-22 00:00:00+03:00,5236.0,53066.0,57.0
|
| 70 |
+
68,2020-04-23 00:00:00+03:00,4774.0,57327.0,42.0
|
| 71 |
+
69,2020-04-24 00:00:00+03:00,5849.0,62439.0,60.0
|
| 72 |
+
70,2020-04-25 00:00:00+03:00,5966.0,67657.0,66.0
|
| 73 |
+
71,2020-04-26 00:00:00+03:00,6361.0,73435.0,66.0
|
| 74 |
+
72,2020-04-27 00:00:00+03:00,6198.0,79007.0,47.0
|
| 75 |
+
73,2020-04-28 00:00:00+03:00,6411.0,84235.0,73.0
|
| 76 |
+
74,2020-04-29 00:00:00+03:00,5841.0,88141.0,105.0
|
| 77 |
+
75,2020-04-30 00:00:00+03:00,7099.0,93806.0,101.0
|
| 78 |
+
76,2020-05-01 00:00:00+03:00,7933.0,100042.0,96.0
|
| 79 |
+
77,2020-05-02 00:00:00+03:00,9623.0,107819.0,53.0
|
| 80 |
+
78,2020-05-03 00:00:00+03:00,10633.0,116768.0,58.0
|
| 81 |
+
79,2020-05-04 00:00:00+03:00,10581.0,125817.0,76.0
|
| 82 |
+
80,2020-05-05 00:00:00+03:00,10102.0,134054.0,95.0
|
| 83 |
+
81,2020-05-06 00:00:00+03:00,10559.0,143065.0,86.0
|
| 84 |
+
82,2020-05-07 00:00:00+03:00,11231.0,151732.0,88.0
|
| 85 |
+
83,2020-05-08 00:00:00+03:00,10699.0,159528.0,98.0
|
| 86 |
+
84,2020-05-09 00:00:00+03:00,10817.0,164933.0,104.0
|
| 87 |
+
85,2020-05-10 00:00:00+03:00,11012.0,173467.0,88.0
|
| 88 |
+
86,2020-05-11 00:00:00+03:00,11656.0,179534.0,94.0
|
| 89 |
+
87,2020-05-12 00:00:00+03:00,10899.0,186615.0,107.0
|
| 90 |
+
88,2020-05-13 00:00:00+03:00,10028.0,192056.0,96.0
|
| 91 |
+
89,2020-05-14 00:00:00+03:00,9974.0,196410.0,93.0
|
| 92 |
+
90,2020-05-15 00:00:00+03:00,10598.0,202199.0,113.0
|
| 93 |
+
91,2020-05-16 00:00:00+03:00,9200.0,206340.0,119.0
|
| 94 |
+
92,2020-05-17 00:00:00+03:00,9709.0,211748.0,94.0
|
| 95 |
+
93,2020-05-18 00:00:00+03:00,8926.0,217747.0,91.0
|
| 96 |
+
94,2020-05-19 00:00:00+03:00,9263.0,220974.0,115.0
|
| 97 |
+
95,2020-05-20 00:00:00+03:00,8764.0,220341.0,135.0
|
| 98 |
+
96,2020-05-21 00:00:00+03:00,8849.0,221774.0,127.0
|
| 99 |
+
97,2020-05-22 00:00:00+03:00,8894.0,223374.0,150.0
|
| 100 |
+
98,2020-05-23 00:00:00+03:00,9434.0,224558.0,139.0
|
| 101 |
+
99,2020-05-24 00:00:00+03:00,8599.0,227641.0,153.0
|
| 102 |
+
100,2020-05-25 00:00:00+03:00,8946.0,230996.0,92.0
|
| 103 |
+
101,2020-05-26 00:00:00+03:00,8915.0,227406.0,174.0
|
| 104 |
+
102,2020-05-27 00:00:00+03:00,8338.0,224504.0,161.0
|
| 105 |
+
103,2020-05-28 00:00:00+03:00,8371.0,223916.0,174.0
|
| 106 |
+
104,2020-05-29 00:00:00+03:00,8572.0,223992.0,232.0
|
| 107 |
+
105,2020-05-30 00:00:00+03:00,8952.0,224551.0,181.0
|
| 108 |
+
106,2020-05-31 00:00:00+03:00,9268.0,229267.0,138.0
|
| 109 |
+
107,2020-06-01 00:00:00+03:00,9035.0,234146.0,162.0
|
| 110 |
+
108,2020-06-02 00:00:00+03:00,8863.0,231719.0,182.0
|
| 111 |
+
109,2020-06-03 00:00:00+03:00,8536.0,231105.0,178.0
|
| 112 |
+
110,2020-06-04 00:00:00+03:00,8831.0,231101.0,169.0
|
| 113 |
+
111,2020-06-05 00:00:00+03:00,8726.0,231626.0,144.0
|
| 114 |
+
112,2020-06-06 00:00:00+03:00,8855.0,231576.0,197.0
|
| 115 |
+
113,2020-06-07 00:00:00+03:00,8984.0,235083.0,134.0
|
| 116 |
+
114,2020-06-08 00:00:00+03:00,8985.0,239999.0,112.0
|
| 117 |
+
115,2020-06-09 00:00:00+03:00,8595.0,236714.0,171.0
|
| 118 |
+
116,2020-06-10 00:00:00+03:00,8404.0,234516.0,216.0
|
| 119 |
+
117,2020-06-11 00:00:00+03:00,8779.0,234754.0,174.0
|
| 120 |
+
118,2020-06-12 00:00:00+03:00,8987.0,235338.0,183.0
|
| 121 |
+
119,2020-06-13 00:00:00+03:00,8706.0,238659.0,114.0
|
| 122 |
+
120,2020-06-14 00:00:00+03:00,8835.0,241966.0,119.0
|
| 123 |
+
121,2020-06-15 00:00:00+03:00,8246.0,245580.0,143.0
|
| 124 |
+
122,2020-06-16 00:00:00+03:00,8248.0,243868.0,193.0
|
| 125 |
+
123,2020-06-17 00:00:00+03:00,7843.0,241481.0,194.0
|
| 126 |
+
124,2020-06-18 00:00:00+03:00,7790.0,239468.0,182.0
|
| 127 |
+
125,2020-06-19 00:00:00+03:00,7972.0,236816.0,181.0
|
| 128 |
+
126,2020-06-20 00:00:00+03:00,7889.0,234358.0,161.0
|
| 129 |
+
127,2020-06-21 00:00:00+03:00,7728.0,236858.0,109.0
|
| 130 |
+
128,2020-06-22 00:00:00+03:00,7600.0,239658.0,95.0
|
| 131 |
+
129,2020-06-23 00:00:00+03:00,7425.0,234917.0,153.0
|
| 132 |
+
130,2020-06-24 00:00:00+03:00,7176.0,229546.0,154.0
|
| 133 |
+
131,2020-06-25 00:00:00+03:00,7113.0,230225.0,92.0
|
| 134 |
+
132,2020-06-26 00:00:00+03:00,6800.0,227861.0,176.0
|
| 135 |
+
133,2020-06-27 00:00:00+03:00,6852.0,225325.0,188.0
|
| 136 |
+
134,2020-06-28 00:00:00+03:00,6791.0,226277.0,104.0
|
| 137 |
+
135,2020-06-29 00:00:00+03:00,6719.0,228560.0,93.0
|
| 138 |
+
136,2020-06-30 00:00:00+03:00,6693.0,225879.0,154.0
|
| 139 |
+
137,2020-07-01 00:00:00+03:00,6556.0,221938.0,216.0
|
| 140 |
+
138,2020-07-02 00:00:00+03:00,6760.0,222504.0,147.0
|
| 141 |
+
139,2020-07-03 00:00:00+03:00,6718.0,220131.0,176.0
|
| 142 |
+
140,2020-07-04 00:00:00+03:00,6632.0,217609.0,168.0
|
| 143 |
+
141,2020-07-05 00:00:00+03:00,6736.0,220340.0,134.0
|
| 144 |
+
142,2020-07-06 00:00:00+03:00,6611.0,223237.0,135.0
|
| 145 |
+
143,2020-07-07 00:00:00+03:00,6368.0,219856.0,198.0
|
| 146 |
+
144,2020-07-08 00:00:00+03:00,6562.0,217614.0,173.0
|
| 147 |
+
145,2020-07-09 00:00:00+03:00,6509.0,215142.0,176.0
|
| 148 |
+
146,2020-07-10 00:00:00+03:00,6635.0,213851.0,174.0
|
| 149 |
+
147,2020-07-11 00:00:00+03:00,6611.0,211896.0,188.0
|
| 150 |
+
148,2020-07-12 00:00:00+03:00,6615.0,214766.0,130.0
|
| 151 |
+
149,2020-07-13 00:00:00+03:00,6537.0,218239.0,104.0
|
| 152 |
+
150,2020-07-14 00:00:00+03:00,6248.0,215508.0,175.0
|
| 153 |
+
151,2020-07-15 00:00:00+03:00,6422.0,211350.0,156.0
|
| 154 |
+
152,2020-07-16 00:00:00+03:00,6428.0,209168.0,167.0
|
| 155 |
+
153,2020-07-17 00:00:00+03:00,6406.0,207707.0,186.0
|
| 156 |
+
154,2020-07-18 00:00:00+03:00,6234.0,206327.0,124.0
|
| 157 |
+
155,2020-07-19 00:00:00+03:00,6109.0,208860.0,95.0
|
| 158 |
+
156,2020-07-20 00:00:00+03:00,5940.0,211457.0,85.0
|
| 159 |
+
157,2020-07-21 00:00:00+03:00,5842.0,208364.0,153.0
|
| 160 |
+
158,2020-07-22 00:00:00+03:00,5862.0,204392.0,165.0
|
| 161 |
+
159,2020-07-23 00:00:00+03:00,5848.0,201816.0,147.0
|
| 162 |
+
160,2020-07-24 00:00:00+03:00,5811.0,199029.0,154.0
|
| 163 |
+
161,2020-07-25 00:00:00+03:00,5871.0,196388.0,146.0
|
| 164 |
+
162,2020-07-26 00:00:00+03:00,5765.0,198966.0,77.0
|
| 165 |
+
163,2020-07-27 00:00:00+03:00,5635.0,201437.0,85.0
|
| 166 |
+
164,2020-07-28 00:00:00+03:00,5395.0,197794.0,150.0
|
| 167 |
+
165,2020-07-29 00:00:00+03:00,5475.0,194984.0,169.0
|
| 168 |
+
166,2020-07-30 00:00:00+03:00,5509.0,191042.0,129.0
|
| 169 |
+
167,2020-07-31 00:00:00+03:00,5482.0,187608.0,161.0
|
| 170 |
+
168,2020-08-01 00:00:00+03:00,5462.0,184861.0,95.0
|
| 171 |
+
169,2020-08-02 00:00:00+03:00,5427.0,186569.0,70.0
|
| 172 |
+
170,2020-08-03 00:00:00+03:00,5394.0,188464.0,79.0
|
| 173 |
+
171,2020-08-04 00:00:00+03:00,5159.0,185601.0,144.0
|
| 174 |
+
172,2020-08-05 00:00:00+03:00,5204.0,183111.0,139.0
|
| 175 |
+
173,2020-08-06 00:00:00+03:00,5267.0,180931.0,116.0
|
| 176 |
+
174,2020-08-07 00:00:00+03:00,5241.0,178818.0,119.0
|
| 177 |
+
175,2020-08-08 00:00:00+03:00,5212.0,177286.0,129.0
|
| 178 |
+
176,2020-08-09 00:00:00+03:00,5189.0,179183.0,77.0
|
| 179 |
+
177,2020-08-10 00:00:00+03:00,5118.0,180972.0,70.0
|
| 180 |
+
178,2020-08-11 00:00:00+03:00,4945.0,179293.0,130.0
|
| 181 |
+
179,2020-08-12 00:00:00+03:00,5102.0,177143.0,129.0
|
| 182 |
+
180,2020-08-13 00:00:00+03:00,5057.0,175978.0,124.0
|
| 183 |
+
181,2020-08-14 00:00:00+03:00,5065.0,174361.0,114.0
|
| 184 |
+
182,2020-08-15 00:00:00+03:00,5061.0,172856.0,119.0
|
| 185 |
+
183,2020-08-16 00:00:00+03:00,4969.0,174200.0,68.0
|
| 186 |
+
184,2020-08-17 00:00:00+03:00,4892.0,175904.0,55.0
|
| 187 |
+
185,2020-08-18 00:00:00+03:00,4748.0,173993.0,132.0
|
| 188 |
+
186,2020-08-19 00:00:00+03:00,4828.0,171909.0,117.0
|
| 189 |
+
187,2020-08-20 00:00:00+03:00,4785.0,170494.0,110.0
|
| 190 |
+
188,2020-08-21 00:00:00+03:00,4870.0,169457.0,90.0
|
| 191 |
+
189,2020-08-22 00:00:00+03:00,4921.0,168110.0,121.0
|
| 192 |
+
190,2020-08-23 00:00:00+03:00,4852.0,169727.0,73.0
|
| 193 |
+
191,2020-08-24 00:00:00+03:00,4744.0,171950.0,65.0
|
| 194 |
+
192,2020-08-25 00:00:00+03:00,4696.0,169874.0,120.0
|
| 195 |
+
193,2020-08-26 00:00:00+03:00,4676.0,168032.0,115.0
|
| 196 |
+
194,2020-08-27 00:00:00+03:00,4711.0,166211.0,121.0
|
| 197 |
+
195,2020-08-28 00:00:00+03:00,4829.0,165025.0,110.0
|
| 198 |
+
196,2020-08-29 00:00:00+03:00,4941.0,163938.0,111.0
|
| 199 |
+
197,2020-08-30 00:00:00+03:00,4980.0,166251.0,68.0
|
| 200 |
+
198,2020-08-31 00:00:00+03:00,4993.0,168756.0,83.0
|
| 201 |
+
199,2020-09-01 00:00:00+03:00,4729.0,167044.0,123.0
|
| 202 |
+
200,2020-09-02 00:00:00+03:00,4952.0,166417.0,115.0
|
| 203 |
+
201,2020-09-03 00:00:00+03:00,4995.0,165532.0,114.0
|
| 204 |
+
202,2020-09-04 00:00:00+03:00,5110.0,164709.0,121.0
|
| 205 |
+
203,2020-09-05 00:00:00+03:00,5205.0,164425.0,110.0
|
| 206 |
+
204,2020-09-06 00:00:00+03:00,5195.0,166736.0,61.0
|
| 207 |
+
205,2020-09-07 00:00:00+03:00,5185.0,169542.0,51.0
|
| 208 |
+
206,2020-09-08 00:00:00+03:00,5099.0,167747.0,122.0
|
| 209 |
+
207,2020-09-09 00:00:00+03:00,5218.0,166414.0,142.0
|
| 210 |
+
208,2020-09-10 00:00:00+03:00,5363.0,165734.0,128.0
|
| 211 |
+
209,2020-09-11 00:00:00+03:00,5504.0,165402.0,102.0
|
| 212 |
+
210,2020-09-12 00:00:00+03:00,5488.0,165343.0,119.0
|
| 213 |
+
211,2020-09-13 00:00:00+03:00,5449.0,168008.0,94.0
|
| 214 |
+
212,2020-09-14 00:00:00+03:00,5509.0,170985.0,57.0
|
| 215 |
+
213,2020-09-15 00:00:00+03:00,5529.0,170759.0,150.0
|
| 216 |
+
214,2020-09-16 00:00:00+03:00,5670.0,170488.0,132.0
|
| 217 |
+
215,2020-09-17 00:00:00+03:00,5762.0,170352.0,144.0
|
| 218 |
+
216,2020-09-18 00:00:00+03:00,5905.0,170784.0,134.0
|
| 219 |
+
217,2020-09-19 00:00:00+03:00,6065.0,171450.0,144.0
|
| 220 |
+
218,2020-09-20 00:00:00+03:00,6148.0,174624.0,79.0
|
| 221 |
+
219,2020-09-21 00:00:00+03:00,6196.0,178133.0,71.0
|
| 222 |
+
220,2020-09-22 00:00:00+03:00,6215.0,178212.0,160.0
|
| 223 |
+
221,2020-09-23 00:00:00+03:00,6431.0,178743.0,150.0
|
| 224 |
+
222,2020-09-24 00:00:00+03:00,6595.0,179059.0,149.0
|
| 225 |
+
223,2020-09-25 00:00:00+03:00,7212.0,181846.0,108.0
|
| 226 |
+
224,2020-09-26 00:00:00+03:00,7523.0,183196.0,169.0
|
| 227 |
+
225,2020-09-27 00:00:00+03:00,7867.0,187896.0,99.0
|
| 228 |
+
226,2020-09-28 00:00:00+03:00,8135.0,193268.0,61.0
|
| 229 |
+
227,2020-09-29 00:00:00+03:00,8232.0,194861.0,160.0
|
| 230 |
+
228,2020-09-30 00:00:00+03:00,8481.0,197307.0,177.0
|
| 231 |
+
229,2020-10-01 00:00:00+03:00,8945.0,200098.0,169.0
|
| 232 |
+
230,2020-10-02 00:00:00+03:00,9412.0,203270.0,186.0
|
| 233 |
+
231,2020-10-03 00:00:00+03:00,9859.0,207392.0,174.0
|
| 234 |
+
232,2020-10-04 00:00:00+03:00,10499.0,214500.0,107.0
|
| 235 |
+
233,2020-10-05 00:00:00+03:00,10888.0,222090.0,117.0
|
| 236 |
+
234,2020-10-06 00:00:00+03:00,11615.0,227265.0,188.0
|
| 237 |
+
235,2020-10-07 00:00:00+03:00,11115.0,231479.0,202.0
|
| 238 |
+
236,2020-10-08 00:00:00+03:00,11493.0,235727.0,191.0
|
| 239 |
+
237,2020-10-09 00:00:00+03:00,12126.0,240560.0,201.0
|
| 240 |
+
238,2020-10-10 00:00:00+03:00,12846.0,246428.0,197.0
|
| 241 |
+
239,2020-10-11 00:00:00+03:00,13634.0,255679.0,143.0
|
| 242 |
+
240,2020-10-12 00:00:00+03:00,13592.0,265353.0,125.0
|
| 243 |
+
241,2020-10-13 00:00:00+03:00,13868.0,271427.0,244.0
|
| 244 |
+
242,2020-10-14 00:00:00+03:00,14231.0,277499.0,239.0
|
| 245 |
+
243,2020-10-15 00:00:00+03:00,13754.0,282575.0,286.0
|
| 246 |
+
244,2020-10-16 00:00:00+03:00,15150.0,289008.0,232.0
|
| 247 |
+
245,2020-10-17 00:00:00+03:00,14922.0,295034.0,279.0
|
| 248 |
+
246,2020-10-18 00:00:00+03:00,15099.0,304571.0,185.0
|
| 249 |
+
247,2020-10-19 00:00:00+03:00,15982.0,315046.0,179.0
|
| 250 |
+
248,2020-10-20 00:00:00+03:00,16319.0,321392.0,269.0
|
| 251 |
+
249,2020-10-21 00:00:00+03:00,15700.0,325823.0,317.0
|
| 252 |
+
250,2020-10-22 00:00:00+03:00,15971.0,330076.0,290.0
|
| 253 |
+
251,2020-10-23 00:00:00+03:00,17340.0,335870.0,283.0
|
| 254 |
+
252,2020-10-24 00:00:00+03:00,16521.0,340528.0,296.0
|
| 255 |
+
253,2020-10-25 00:00:00+03:00,16710.0,349305.0,229.0
|
| 256 |
+
254,2020-10-26 00:00:00+03:00,17347.0,358859.0,219.0
|
| 257 |
+
255,2020-10-27 00:00:00+03:00,16550.0,362245.0,320.0
|
| 258 |
+
256,2020-10-28 00:00:00+03:00,16202.0,365740.0,346.0
|
| 259 |
+
257,2020-10-29 00:00:00+03:00,17717.0,368351.0,366.0
|
| 260 |
+
258,2020-10-30 00:00:00+03:00,18283.0,371760.0,355.0
|
| 261 |
+
259,2020-10-31 00:00:00+03:00,18140.0,374712.0,334.0
|
| 262 |
+
260,2020-11-01 00:00:00+03:00,18665.0,382873.0,245.0
|
| 263 |
+
261,2020-11-02 00:00:00+03:00,18257.0,390532.0,238.0
|
| 264 |
+
262,2020-11-03 00:00:00+03:00,18648.0,393494.0,355.0
|
| 265 |
+
263,2020-11-04 00:00:00+03:00,19768.0,397306.0,389.0
|
| 266 |
+
264,2020-11-05 00:00:00+03:00,19404.0,404180.0,292.0
|
| 267 |
+
265,2020-11-06 00:00:00+03:00,20582.0,407429.0,378.0
|
| 268 |
+
266,2020-11-07 00:00:00+03:00,20396.0,410658.0,364.0
|
| 269 |
+
267,2020-11-08 00:00:00+03:00,20498.0,419378.0,286.0
|
| 270 |
+
268,2020-11-09 00:00:00+03:00,21798.0,430198.0,256.0
|
| 271 |
+
269,2020-11-10 00:00:00+03:00,20977.0,435207.0,368.0
|
| 272 |
+
270,2020-11-11 00:00:00+03:00,19851.0,436010.0,432.0
|
| 273 |
+
271,2020-11-12 00:00:00+03:00,21608.0,438368.0,439.0
|
| 274 |
+
272,2020-11-13 00:00:00+03:00,21983.0,441205.0,411.0
|
| 275 |
+
273,2020-11-14 00:00:00+03:00,22702.0,444890.0,391.0
|
| 276 |
+
274,2020-11-15 00:00:00+03:00,22572.0,452654.0,352.0
|
| 277 |
+
275,2020-11-16 00:00:00+03:00,22778.0,461265.0,303.0
|
| 278 |
+
276,2020-11-17 00:00:00+03:00,22410.0,461178.0,442.0
|
| 279 |
+
277,2020-11-18 00:00:00+03:00,20985.0,456528.0,456.0
|
| 280 |
+
278,2020-11-19 00:00:00+03:00,23610.0,454102.0,463.0
|
| 281 |
+
279,2020-11-20 00:00:00+03:00,24318.0,453201.0,461.0
|
| 282 |
+
280,2020-11-21 00:00:00+03:00,24822.0,451535.0,467.0
|
| 283 |
+
281,2020-11-22 00:00:00+03:00,24581.0,457707.0,401.0
|
| 284 |
+
282,2020-11-23 00:00:00+03:00,25173.0,466517.0,361.0
|
| 285 |
+
283,2020-11-24 00:00:00+03:00,24326.0,467126.0,491.0
|
| 286 |
+
284,2020-11-25 00:00:00+03:00,23675.0,464546.0,507.0
|
| 287 |
+
285,2020-11-26 00:00:00+03:00,25487.0,464436.0,524.0
|
| 288 |
+
286,2020-11-27 00:00:00+03:00,27543.0,464801.0,496.0
|
| 289 |
+
287,2020-11-28 00:00:00+03:00,27100.0,464095.0,510.0
|
| 290 |
+
288,2020-11-29 00:00:00+03:00,26683.0,468332.0,459.0
|
| 291 |
+
289,2020-11-30 00:00:00+03:00,26338.0,477055.0,368.0
|
| 292 |
+
290,2020-12-01 00:00:00+03:00,26402.0,478125.0,569.0
|
| 293 |
+
291,2020-12-02 00:00:00+03:00,25345.0,475999.0,589.0
|
| 294 |
+
292,2020-12-03 00:00:00+03:00,28145.0,474088.0,554.0
|
| 295 |
+
293,2020-12-04 00:00:00+03:00,27403.0,472021.0,569.0
|
| 296 |
+
294,2020-12-05 00:00:00+03:00,28782.0,472651.0,508.0
|
| 297 |
+
295,2020-12-06 00:00:00+03:00,29039.0,479891.0,457.0
|
| 298 |
+
296,2020-12-07 00:00:00+03:00,28142.0,488727.0,456.0
|
| 299 |
+
297,2020-12-08 00:00:00+03:00,26097.0,489324.0,562.0
|
| 300 |
+
298,2020-12-09 00:00:00+03:00,26190.0,488689.0,559.0
|
| 301 |
+
299,2020-12-10 00:00:00+03:00,27927.0,490177.0,562.0
|
| 302 |
+
300,2020-12-11 00:00:00+03:00,28585.0,491978.0,613.0
|
| 303 |
+
301,2020-12-12 00:00:00+03:00,28137.0,493437.0,560.0
|
| 304 |
+
302,2020-12-13 00:00:00+03:00,28080.0,500752.0,488.0
|
| 305 |
+
303,2020-12-14 00:00:00+03:00,27328.0,509068.0,450.0
|
| 306 |
+
304,2020-12-15 00:00:00+03:00,26689.0,510367.0,577.0
|
| 307 |
+
305,2020-12-16 00:00:00+03:00,26509.0,509790.0,596.0
|
| 308 |
+
306,2020-12-17 00:00:00+03:00,28214.0,510977.0,587.0
|
| 309 |
+
307,2020-12-18 00:00:00+03:00,28552.0,512825.0,611.0
|
| 310 |
+
308,2020-12-19 00:00:00+03:00,28209.0,514340.0,585.0
|
| 311 |
+
309,2020-12-20 00:00:00+03:00,28948.0,521862.0,511.0
|
| 312 |
+
310,2020-12-21 00:00:00+03:00,29350.0,531014.0,493.0
|
| 313 |
+
311,2020-12-22 00:00:00+03:00,28776.0,535071.0,561.0
|
| 314 |
+
312,2020-12-23 00:00:00+03:00,27250.0,537325.0,549.0
|
| 315 |
+
313,2020-12-24 00:00:00+03:00,29935.0,539735.0,635.0
|
| 316 |
+
314,2020-12-25 00:00:00+03:00,29018.0,540793.0,563.0
|
| 317 |
+
315,2020-12-26 00:00:00+03:00,29258.0,541299.0,567.0
|
| 318 |
+
316,2020-12-27 00:00:00+03:00,28284.0,544641.0,552.0
|
| 319 |
+
317,2020-12-28 00:00:00+03:00,27787.0,551461.0,487.0
|
| 320 |
+
318,2020-12-29 00:00:00+03:00,27002.0,553027.0,562.0
|
| 321 |
+
319,2020-12-30 00:00:00+03:00,26513.0,549706.0,599.0
|
| 322 |
+
320,2020-12-31 00:00:00+03:00,27747.0,547938.0,593.0
|
| 323 |
+
321,2021-01-01 00:00:00+03:00,27039.0,548643.0,536.0
|
| 324 |
+
322,2021-01-02 00:00:00+03:00,26301.0,555600.0,447.0
|
| 325 |
+
323,2021-01-03 00:00:00+03:00,24150.0,559399.0,504.0
|
| 326 |
+
324,2021-01-04 00:00:00+03:00,23351.0,561114.0,482.0
|
| 327 |
+
325,2021-01-05 00:00:00+03:00,24246.0,562210.0,518.0
|
| 328 |
+
326,2021-01-06 00:00:00+03:00,24217.0,562927.0,445.0
|
| 329 |
+
327,2021-01-07 00:00:00+03:00,23541.0,562233.0,506.0
|
| 330 |
+
328,2021-01-08 00:00:00+03:00,23652.0,563754.0,454.0
|
| 331 |
+
329,2021-01-09 00:00:00+03:00,23309.0,562913.0,470.0
|
| 332 |
+
330,2021-01-10 00:00:00+03:00,22851.0,561228.0,456.0
|
| 333 |
+
331,2021-01-11 00:00:00+03:00,23315.0,562321.0,436.0
|
| 334 |
+
332,2021-01-12 00:00:00+03:00,22934.0,559969.0,531.0
|
| 335 |
+
333,2021-01-13 00:00:00+03:00,22850.0,553595.0,566.0
|
| 336 |
+
334,2021-01-14 00:00:00+03:00,24763.0,549832.0,570.0
|
| 337 |
+
335,2021-01-15 00:00:00+03:00,24715.0,546356.0,555.0
|
| 338 |
+
336,2021-01-16 00:00:00+03:00,24092.0,542547.0,590.0
|
| 339 |
+
337,2021-01-17 00:00:00+03:00,23586.0,542212.0,481.0
|
| 340 |
+
338,2021-01-18 00:00:00+03:00,22857.0,546265.0,471.0
|
| 341 |
+
339,2021-01-19 00:00:00+03:00,21734.0,544151.0,586.0
|
| 342 |
+
340,2021-01-20 00:00:00+03:00,21152.0,539416.0,597.0
|
| 343 |
+
341,2021-01-21 00:00:00+03:00,21887.0,533789.0,612.0
|
| 344 |
+
342,2021-01-22 00:00:00+03:00,21513.0,527404.0,580.0
|
| 345 |
+
343,2021-01-23 00:00:00+03:00,20921.0,519987.0,559.0
|
| 346 |
+
344,2021-01-24 00:00:00+03:00,21127.0,518178.0,491.0
|
| 347 |
+
345,2021-01-25 00:00:00+03:00,19290.0,518009.0,456.0
|
| 348 |
+
346,2021-01-26 00:00:00+03:00,18241.0,511888.0,564.0
|
| 349 |
+
347,2021-01-27 00:00:00+03:00,17741.0,501113.0,594.0
|
| 350 |
+
348,2021-01-28 00:00:00+03:00,19138.0,492901.0,575.0
|
| 351 |
+
349,2021-01-29 00:00:00+03:00,19238.0,485401.0,534.0
|
| 352 |
+
350,2021-01-30 00:00:00+03:00,19032.0,479419.0,512.0
|
| 353 |
+
351,2021-01-31 00:00:00+03:00,18359.0,477253.0,485.0
|
| 354 |
+
352,2021-02-01 00:00:00+03:00,17648.0,476295.0,437.0
|
| 355 |
+
353,2021-02-02 00:00:00+03:00,16643.0,470027.0,539.0
|
| 356 |
+
354,2021-02-03 00:00:00+03:00,16474.0,461153.0,526.0
|
| 357 |
+
355,2021-02-04 00:00:00+03:00,16714.0,452800.0,521.0
|
| 358 |
+
356,2021-02-05 00:00:00+03:00,16688.0,445379.0,527.0
|
| 359 |
+
357,2021-02-06 00:00:00+03:00,16627.0,438678.0,497.0
|
| 360 |
+
358,2021-02-07 00:00:00+03:00,16048.0,434410.0,432.0
|
| 361 |
+
359,2021-02-08 00:00:00+03:00,15916.0,434038.0,407.0
|
| 362 |
+
360,2021-02-09 00:00:00+03:00,15019.0,426732.0,530.0
|
| 363 |
+
361,2021-02-10 00:00:00+03:00,14494.0,418115.0,536.0
|
| 364 |
+
362,2021-02-11 00:00:00+03:00,15038.0,410639.0,553.0
|
| 365 |
+
363,2021-02-12 00:00:00+03:00,15089.0,404501.0,507.0
|
| 366 |
+
364,2021-02-13 00:00:00+03:00,14861.0,400095.0,502.0
|
| 367 |
+
365,2021-02-14 00:00:00+03:00,14185.0,398656.0,430.0
|
| 368 |
+
366,2021-02-15 00:00:00+03:00,14207.0,398534.0,394.0
|
| 369 |
+
367,2021-02-16 00:00:00+03:00,13233.0,393681.0,459.0
|
| 370 |
+
368,2021-02-17 00:00:00+03:00,12828.0,388123.0,467.0
|
| 371 |
+
369,2021-02-18 00:00:00+03:00,13447.0,382360.0,480.0
|
| 372 |
+
370,2021-02-19 00:00:00+03:00,13433.0,376686.0,470.0
|
| 373 |
+
371,2021-02-20 00:00:00+03:00,12953.0,371675.0,480.0
|
| 374 |
+
372,2021-02-21 00:00:00+03:00,12742.0,367988.0,417.0
|
| 375 |
+
373,2021-02-22 00:00:00+03:00,12604.0,367312.0,337.0
|
| 376 |
+
374,2021-02-23 00:00:00+03:00,11823.0,365762.0,417.0
|
| 377 |
+
375,2021-02-24 00:00:00+03:00,11749.0,364910.0,383.0
|
| 378 |
+
376,2021-02-25 00:00:00+03:00,11198.0,359560.0,446.0
|
| 379 |
+
377,2021-02-26 00:00:00+03:00,11086.0,354496.0,428.0
|
| 380 |
+
378,2021-02-27 00:00:00+03:00,11534.0,349571.0,439.0
|
| 381 |
+
379,2021-02-28 00:00:00+03:00,11359.0,348160.0,379.0
|
| 382 |
+
380,2021-03-01 00:00:00+03:00,11571.0,348121.0,333.0
|
| 383 |
+
381,2021-03-02 00:00:00+03:00,10565.0,343279.0,441.0
|
| 384 |
+
382,2021-03-03 00:00:00+03:00,10535.0,337668.0,452.0
|
| 385 |
+
383,2021-03-04 00:00:00+03:00,11385.0,332455.0,475.0
|
| 386 |
+
384,2021-03-05 00:00:00+03:00,11024.0,327553.0,462.0
|
| 387 |
+
385,2021-03-06 00:00:00+03:00,11022.0,323107.0,441.0
|
| 388 |
+
386,2021-03-07 00:00:00+03:00,10595.0,321758.0,368.0
|
| 389 |
+
387,2021-03-08 00:00:00+03:00,10253.0,321310.0,379.0
|
| 390 |
+
388,2021-03-09 00:00:00+03:00,9445.0,320488.0,336.0
|
| 391 |
+
389,2021-03-10 00:00:00+03:00,9079.0,315751.0,466.0
|
| 392 |
+
390,2021-03-11 00:00:00+03:00,9270.0,310556.0,459.0
|
| 393 |
+
391,2021-03-12 00:00:00+03:00,9794.0,306368.0,486.0
|
| 394 |
+
392,2021-03-13 00:00:00+03:00,9908.0,302933.0,475.0
|
| 395 |
+
393,2021-03-14 00:00:00+03:00,10083.0,303209.0,395.0
|
| 396 |
+
394,2021-03-15 00:00:00+03:00,9437.0,303975.0,404.0
|
| 397 |
+
395,2021-03-16 00:00:00+03:00,9393.0,302281.0,443.0
|
| 398 |
+
396,2021-03-17 00:00:00+03:00,8998.0,300097.0,427.0
|
| 399 |
+
397,2021-03-18 00:00:00+03:00,9803.0,297379.0,460.0
|
| 400 |
+
398,2021-03-19 00:00:00+03:00,9699.0,294298.0,443.0
|
| 401 |
+
399,2021-03-20 00:00:00+03:00,9632.0,292259.0,392.0
|
| 402 |
+
400,2021-03-21 00:00:00+03:00,9299.0,292444.0,371.0
|
| 403 |
+
401,2021-03-22 00:00:00+03:00,9284.0,293577.0,361.0
|
| 404 |
+
402,2021-03-23 00:00:00+03:00,8457.0,290747.0,427.0
|
| 405 |
+
403,2021-03-24 00:00:00+03:00,8861.0,288852.0,401.0
|
| 406 |
+
404,2021-03-25 00:00:00+03:00,9221.0,286799.0,393.0
|
| 407 |
+
405,2021-03-26 00:00:00+03:00,9167.0,284681.0,405.0
|
| 408 |
+
406,2021-03-27 00:00:00+03:00,8885.0,282842.0,387.0
|
| 409 |
+
407,2021-03-28 00:00:00+03:00,9088.0,282964.0,336.0
|
| 410 |
+
408,2021-03-29 00:00:00+03:00,8711.0,284102.0,293.0
|
| 411 |
+
409,2021-03-30 00:00:00+03:00,8277.0,282382.0,409.0
|
| 412 |
+
410,2021-03-31 00:00:00+03:00,8275.0,280073.0,408.0
|
| 413 |
+
411,2021-04-01 00:00:00+03:00,9169.0,278612.0,383.0
|
| 414 |
+
412,2021-04-02 00:00:00+03:00,8792.0,277172.0,400.0
|
| 415 |
+
413,2021-04-03 00:00:00+03:00,9021.0,276191.0,384.0
|
| 416 |
+
414,2021-04-04 00:00:00+03:00,8817.0,276439.0,357.0
|
| 417 |
+
415,2021-04-05 00:00:00+03:00,8646.0,277690.0,343.0
|
| 418 |
+
416,2021-04-06 00:00:00+03:00,8328.0,276727.0,389.0
|
| 419 |
+
417,2021-04-07 00:00:00+03:00,8294.0,275202.0,374.0
|
| 420 |
+
418,2021-04-08 00:00:00+03:00,8672.0,273951.0,365.0
|
| 421 |
+
419,2021-04-09 00:00:00+03:00,9150.0,273037.0,402.0
|
| 422 |
+
420,2021-04-10 00:00:00+03:00,8704.0,271760.0,402.0
|
| 423 |
+
421,2021-04-11 00:00:00+03:00,8702.0,272895.0,337.0
|
| 424 |
+
422,2021-04-12 00:00:00+03:00,8320.0,274282.0,277.0
|
| 425 |
+
423,2021-04-13 00:00:00+03:00,8173.0,272506.0,338.0
|
| 426 |
+
424,2021-04-14 00:00:00+03:00,8326.0,270986.0,399.0
|
| 427 |
+
425,2021-04-15 00:00:00+03:00,8944.0,269307.0,398.0
|
| 428 |
+
426,2021-04-16 00:00:00+03:00,8995.0,268796.0,397.0
|
| 429 |
+
427,2021-04-17 00:00:00+03:00,9321.0,268887.0,398.0
|
| 430 |
+
428,2021-04-18 00:00:00+03:00,8632.0,269739.0,389.0
|
| 431 |
+
429,2021-04-19 00:00:00+03:00,8589.0,271164.0,346.0
|
| 432 |
+
430,2021-04-20 00:00:00+03:00,8164.0,269318.0,379.0
|
| 433 |
+
431,2021-04-21 00:00:00+03:00,8271.0,267546.0,399.0
|
| 434 |
+
432,2021-04-22 00:00:00+03:00,8996.0,267211.0,397.0
|
| 435 |
+
433,2021-04-23 00:00:00+03:00,8840.0,266246.0,398.0
|
| 436 |
+
434,2021-04-24 00:00:00+03:00,8828.0,265421.0,399.0
|
| 437 |
+
435,2021-04-25 00:00:00+03:00,8780.0,266329.0,332.0
|
| 438 |
+
436,2021-04-26 00:00:00+03:00,8803.0,268145.0,356.0
|
| 439 |
+
437,2021-04-27 00:00:00+03:00,8053.0,267767.0,392.0
|
| 440 |
+
438,2021-04-28 00:00:00+03:00,7848.0,266808.0,387.0
|
| 441 |
+
439,2021-04-29 00:00:00+03:00,9284.0,267286.0,364.0
|
| 442 |
+
440,2021-04-30 00:00:00+03:00,8731.0,267214.0,397.0
|
| 443 |
+
441,2021-05-01 00:00:00+03:00,9270.0,267455.0,392.0
|
| 444 |
+
442,2021-05-02 00:00:00+03:00,8697.0,268471.0,342.0
|
| 445 |
+
443,2021-05-03 00:00:00+03:00,8489.0,270257.0,336.0
|
| 446 |
+
444,2021-05-04 00:00:00+03:00,7770.0,270935.0,337.0
|
| 447 |
+
445,2021-05-05 00:00:00+03:00,7975.0,271044.0,360.0
|
| 448 |
+
446,2021-05-06 00:00:00+03:00,7639.0,270544.0,351.0
|
| 449 |
+
447,2021-05-07 00:00:00+03:00,8386.0,270532.0,376.0
|
| 450 |
+
448,2021-05-08 00:00:00+03:00,8329.0,270236.0,370.0
|
| 451 |
+
449,2021-05-09 00:00:00+03:00,8419.0,270804.0,334.0
|
| 452 |
+
450,2021-05-10 00:00:00+03:00,8465.0,272174.0,321.0
|
| 453 |
+
451,2021-05-11 00:00:00+03:00,8115.0,272951.0,329.0
|
| 454 |
+
452,2021-05-12 00:00:00+03:00,8217.0,272199.0,355.0
|
| 455 |
+
453,2021-05-13 00:00:00+03:00,8380.0,270838.0,392.0
|
| 456 |
+
454,2021-05-14 00:00:00+03:00,9462.0,270151.0,393.0
|
| 457 |
+
455,2021-05-15 00:00:00+03:00,8790.0,268711.0,364.0
|
| 458 |
+
456,2021-05-16 00:00:00+03:00,8554.0,268301.0,391.0
|
| 459 |
+
457,2021-05-17 00:00:00+03:00,9328.0,270108.0,340.0
|
| 460 |
+
458,2021-05-18 00:00:00+03:00,8183.0,268955.0,364.0
|
| 461 |
+
459,2021-05-19 00:00:00+03:00,7920.0,266924.0,390.0
|
| 462 |
+
460,2021-05-20 00:00:00+03:00,9232.0,265777.0,396.0
|
| 463 |
+
461,2021-05-21 00:00:00+03:00,8937.0,264986.0,378.0
|
| 464 |
+
462,2021-05-22 00:00:00+03:00,8709.0,263964.0,386.0
|
| 465 |
+
463,2021-05-23 00:00:00+03:00,8951.0,265261.0,357.0
|
| 466 |
+
464,2021-05-24 00:00:00+03:00,8406.0,266898.0,319.0
|
| 467 |
+
465,2021-05-25 00:00:00+03:00,7884.0,265646.0,393.0
|
| 468 |
+
466,2021-05-26 00:00:00+03:00,8373.0,264478.0,406.0
|
| 469 |
+
467,2021-05-27 00:00:00+03:00,9039.0,263356.0,402.0
|
| 470 |
+
468,2021-05-28 00:00:00+03:00,9252.0,262819.0,404.0
|
| 471 |
+
469,2021-05-29 00:00:00+03:00,9289.0,262457.0,401.0
|
| 472 |
+
470,2021-05-30 00:00:00+03:00,9694.0,264410.0,355.0
|
| 473 |
+
471,2021-05-31 00:00:00+03:00,8475.0,265831.0,339.0
|
| 474 |
+
472,2021-06-01 00:00:00+03:00,9500.0,265965.0,372.0
|
| 475 |
+
473,2021-06-02 00:00:00+03:00,8832.0,265383.0,394.0
|
| 476 |
+
474,2021-06-03 00:00:00+03:00,8933.0,264540.0,393.0
|
| 477 |
+
475,2021-06-04 00:00:00+03:00,8947.0,264580.0,377.0
|
| 478 |
+
476,2021-06-05 00:00:00+03:00,9145.0,264761.0,399.0
|
| 479 |
+
477,2021-06-06 00:00:00+03:00,9163.0,266204.0,351.0
|
| 480 |
+
478,2021-06-07 00:00:00+03:00,9429.0,268547.0,330.0
|
| 481 |
+
479,2021-06-08 00:00:00+03:00,9977.0,269262.0,379.0
|
| 482 |
+
480,2021-06-09 00:00:00+03:00,10407.0,269456.0,399.0
|
| 483 |
+
481,2021-06-10 00:00:00+03:00,11699.0,270676.0,383.0
|
| 484 |
+
482,2021-06-11 00:00:00+03:00,12505.0,272597.0,396.0
|
| 485 |
+
483,2021-06-12 00:00:00+03:00,13510.0,275722.0,399.0
|
| 486 |
+
484,2021-06-13 00:00:00+03:00,14723.0,280922.0,357.0
|
| 487 |
+
485,2021-06-14 00:00:00+03:00,13721.0,285960.0,371.0
|
| 488 |
+
486,2021-06-15 00:00:00+03:00,14185.0,291169.0,379.0
|
| 489 |
+
487,2021-06-16 00:00:00+03:00,13397.0,293914.0,396.0
|
| 490 |
+
488,2021-06-17 00:00:00+03:00,14057.0,296350.0,416.0
|
| 491 |
+
489,2021-06-18 00:00:00+03:00,17262.0,302205.0,453.0
|
| 492 |
+
490,2021-06-19 00:00:00+03:00,17906.0,308961.0,466.0
|
| 493 |
+
491,2021-06-20 00:00:00+03:00,17611.0,317493.0,450.0
|
| 494 |
+
492,2021-06-21 00:00:00+03:00,17378.0,326070.0,440.0
|
| 495 |
+
493,2021-06-22 00:00:00+03:00,16715.0,331122.0,546.0
|
| 496 |
+
494,2021-06-23 00:00:00+03:00,17594.0,335508.0,548.0
|
| 497 |
+
495,2021-06-24 00:00:00+03:00,20182.0,341617.0,568.0
|
| 498 |
+
496,2021-06-25 00:00:00+03:00,20393.0,347385.0,601.0
|
| 499 |
+
497,2021-06-26 00:00:00+03:00,21665.0,354084.0,619.0
|
| 500 |
+
498,2021-06-27 00:00:00+03:00,20538.0,361295.0,599.0
|
| 501 |
+
499,2021-06-28 00:00:00+03:00,21650.0,369708.0,611.0
|
| 502 |
+
500,2021-06-29 00:00:00+03:00,20616.0,374975.0,652.0
|
| 503 |
+
501,2021-06-30 00:00:00+03:00,21042.0,378992.0,669.0
|
| 504 |
+
502,2021-07-01 00:00:00+03:00,23543.0,384935.0,672.0
|
| 505 |
+
503,2021-07-02 00:00:00+03:00,23218.0,389277.0,679.0
|
| 506 |
+
504,2021-07-03 00:00:00+03:00,24439.0,395120.0,697.0
|
| 507 |
+
505,2021-07-04 00:00:00+03:00,25142.0,404115.0,663.0
|
| 508 |
+
506,2021-07-05 00:00:00+03:00,24353.0,413274.0,654.0
|
| 509 |
+
507,2021-07-06 00:00:00+03:00,23378.0,417504.0,737.0
|
| 510 |
+
508,2021-07-07 00:00:00+03:00,23962.0,420674.0,725.0
|
| 511 |
+
509,2021-07-08 00:00:00+03:00,24818.0,423422.0,734.0
|
| 512 |
+
510,2021-07-09 00:00:00+03:00,25766.0,426630.0,726.0
|
| 513 |
+
511,2021-07-10 00:00:00+03:00,25082.0,433210.0,752.0
|
| 514 |
+
512,2021-07-11 00:00:00+03:00,25033.0,440112.0,749.0
|
| 515 |
+
513,2021-07-12 00:00:00+03:00,25140.0,448113.0,710.0
|
| 516 |
+
514,2021-07-13 00:00:00+03:00,24702.0,452469.0,780.0
|
| 517 |
+
515,2021-07-14 00:00:00+03:00,23827.0,454241.0,786.0
|
| 518 |
+
516,2021-07-15 00:00:00+03:00,25293.0,457250.0,791.0
|
| 519 |
+
517,2021-07-16 00:00:00+03:00,25704.0,460223.0,799.0
|
| 520 |
+
518,2021-07-17 00:00:00+03:00,25116.0,463115.0,787.0
|
| 521 |
+
519,2021-07-18 00:00:00+03:00,25018.0,468483.0,764.0
|
| 522 |
+
520,2021-07-19 00:00:00+03:00,24633.0,473633.0,719.0
|
| 523 |
+
521,2021-07-20 00:00:00+03:00,23770.0,474401.0,784.0
|
| 524 |
+
522,2021-07-21 00:00:00+03:00,23704.0,474738.0,783.0
|
| 525 |
+
523,2021-07-22 00:00:00+03:00,24471.0,475753.0,796.0
|
| 526 |
+
524,2021-07-23 00:00:00+03:00,23811.0,476222.0,795.0
|
| 527 |
+
525,2021-07-24 00:00:00+03:00,23947.0,477418.0,799.0
|
| 528 |
+
526,2021-07-25 00:00:00+03:00,24072.0,482033.0,779.0
|
| 529 |
+
527,2021-07-26 00:00:00+03:00,23239.0,488345.0,727.0
|
| 530 |
+
528,2021-07-27 00:00:00+03:00,23032.0,490482.0,779.0
|
| 531 |
+
529,2021-07-28 00:00:00+03:00,22420.0,491525.0,798.0
|
| 532 |
+
530,2021-07-29 00:00:00+03:00,23270.0,493162.0,799.0
|
| 533 |
+
531,2021-07-30 00:00:00+03:00,23564.0,495447.0,794.0
|
| 534 |
+
532,2021-07-31 00:00:00+03:00,23807.0,498691.0,792.0
|
| 535 |
+
533,2021-08-01 00:00:00+03:00,22804.0,503435.0,789.0
|
| 536 |
+
534,2021-08-02 00:00:00+03:00,23508.0,511265.0,785.0
|
| 537 |
+
535,2021-08-03 00:00:00+03:00,22010.0,513524.0,788.0
|
| 538 |
+
536,2021-08-04 00:00:00+03:00,22589.0,515227.0,790.0
|
| 539 |
+
537,2021-08-05 00:00:00+03:00,23120.0,517183.0,794.0
|
| 540 |
+
538,2021-08-06 00:00:00+03:00,22660.0,518910.0,792.0
|
| 541 |
+
539,2021-08-07 00:00:00+03:00,22320.0,520952.0,793.0
|
| 542 |
+
540,2021-08-08 00:00:00+03:00,22866.0,527362.0,787.0
|
| 543 |
+
541,2021-08-09 00:00:00+03:00,22160.0,534279.0,769.0
|
| 544 |
+
542,2021-08-10 00:00:00+03:00,21378.0,536136.0,792.0
|
| 545 |
+
543,2021-08-11 00:00:00+03:00,21571.0,536841.0,799.0
|
| 546 |
+
544,2021-08-12 00:00:00+03:00,21932.0,537770.0,808.0
|
| 547 |
+
545,2021-08-13 00:00:00+03:00,22277.0,539864.0,815.0
|
| 548 |
+
546,2021-08-14 00:00:00+03:00,22144.0,541639.0,819.0
|
| 549 |
+
547,2021-08-15 00:00:00+03:00,21624.0,546021.0,816.0
|
| 550 |
+
548,2021-08-16 00:00:00+03:00,20765.0,550379.0,806.0
|
| 551 |
+
549,2021-08-17 00:00:00+03:00,20958.0,552125.0,805.0
|
| 552 |
+
550,2021-08-18 00:00:00+03:00,20914.0,551527.0,799.0
|
| 553 |
+
551,2021-08-19 00:00:00+03:00,21058.0,547777.0,791.0
|
| 554 |
+
552,2021-08-20 00:00:00+03:00,20992.0,547633.0,785.0
|
| 555 |
+
553,2021-08-21 00:00:00+03:00,21000.0,547189.0,797.0
|
| 556 |
+
554,2021-08-22 00:00:00+03:00,20564.0,551577.0,762.0
|
| 557 |
+
555,2021-08-23 00:00:00+03:00,19454.0,554854.0,776.0
|
| 558 |
+
556,2021-08-24 00:00:00+03:00,18833.0,554257.0,794.0
|
| 559 |
+
557,2021-08-25 00:00:00+03:00,19536.0,553330.0,809.0
|
| 560 |
+
558,2021-08-26 00:00:00+03:00,19630.0,552479.0,820.0
|
| 561 |
+
559,2021-08-27 00:00:00+03:00,19509.0,551973.0,798.0
|
| 562 |
+
560,2021-08-28 00:00:00+03:00,19492.0,551255.0,799.0
|
| 563 |
+
561,2021-08-29 00:00:00+03:00,19286.0,552940.0,797.0
|
| 564 |
+
562,2021-08-30 00:00:00+03:00,18325.0,556293.0,792.0
|
| 565 |
+
563,2021-08-31 00:00:00+03:00,17813.0,554687.0,795.0
|
| 566 |
+
564,2021-09-01 00:00:00+03:00,18368.0,553940.0,790.0
|
| 567 |
+
565,2021-09-02 00:00:00+03:00,18985.0,553458.0,798.0
|
| 568 |
+
566,2021-09-03 00:00:00+03:00,18856.0,552825.0,799.0
|
| 569 |
+
567,2021-09-04 00:00:00+03:00,18780.0,552072.0,796.0
|
| 570 |
+
568,2021-09-05 00:00:00+03:00,18645.0,554668.0,793.0
|
| 571 |
+
569,2021-09-06 00:00:00+03:00,17856.0,557458.0,790.0
|
| 572 |
+
570,2021-09-07 00:00:00+03:00,17425.0,556845.0,795.0
|
| 573 |
+
571,2021-09-08 00:00:00+03:00,18024.0,555810.0,797.0
|
| 574 |
+
572,2021-09-09 00:00:00+03:00,18380.0,553757.0,794.0
|
| 575 |
+
573,2021-09-10 00:00:00+03:00,18341.0,554188.0,789.0
|
| 576 |
+
574,2021-09-11 00:00:00+03:00,18891.0,554395.0,796.0
|
| 577 |
+
575,2021-09-12 00:00:00+03:00,18554.0,557664.0,788.0
|
| 578 |
+
576,2021-09-13 00:00:00+03:00,18178.0,562654.0,719.0
|
| 579 |
+
577,2021-09-14 00:00:00+03:00,17837.0,563803.0,781.0
|
| 580 |
+
578,2021-09-15 00:00:00+03:00,18841.0,564813.0,792.0
|
| 581 |
+
579,2021-09-16 00:00:00+03:00,19594.0,566287.0,794.0
|
| 582 |
+
580,2021-09-17 00:00:00+03:00,19905.0,568782.0,791.0
|
| 583 |
+
581,2021-09-18 00:00:00+03:00,20329.0,572065.0,799.0
|
| 584 |
+
582,2021-09-19 00:00:00+03:00,20174.0,578028.0,793.0
|
| 585 |
+
583,2021-09-20 00:00:00+03:00,19744.0,585002.0,778.0
|
| 586 |
+
584,2021-09-21 00:00:00+03:00,19179.0,587932.0,812.0
|
| 587 |
+
585,2021-09-22 00:00:00+03:00,19706.0,590719.0,817.0
|
| 588 |
+
586,2021-09-23 00:00:00+03:00,21438.0,594770.0,820.0
|
| 589 |
+
587,2021-09-24 00:00:00+03:00,21379.0,599493.0,828.0
|
| 590 |
+
588,2021-09-25 00:00:00+03:00,22041.0,604387.0,822.0
|
| 591 |
+
589,2021-09-26 00:00:00+03:00,22498.0,612409.0,805.0
|
| 592 |
+
590,2021-09-27 00:00:00+03:00,22236.0,620353.0,779.0
|
| 593 |
+
591,2021-09-28 00:00:00+03:00,21559.0,623692.0,852.0
|
| 594 |
+
592,2021-09-29 00:00:00+03:00,22430.0,626809.0,857.0
|
| 595 |
+
593,2021-09-30 00:00:00+03:00,23888.0,631004.0,867.0
|
| 596 |
+
594,2021-10-01 00:00:00+03:00,24522.0,634684.0,887.0
|
| 597 |
+
595,2021-10-02 00:00:00+03:00,25219.0,641165.0,886.0
|
| 598 |
+
596,2021-10-03 00:00:00+03:00,25769.0,650653.0,890.0
|
| 599 |
+
597,2021-10-04 00:00:00+03:00,25781.0,661025.0,883.0
|
| 600 |
+
598,2021-10-05 00:00:00+03:00,25110.0,666672.0,895.0
|
| 601 |
+
599,2021-10-06 00:00:00+03:00,25133.0,671035.0,929.0
|
| 602 |
+
600,2021-10-07 00:00:00+03:00,27550.0,677331.0,924.0
|
| 603 |
+
601,2021-10-08 00:00:00+03:00,27246.0,683075.0,936.0
|
| 604 |
+
602,2021-10-09 00:00:00+03:00,29362.0,690420.0,968.0
|
| 605 |
+
603,2021-10-10 00:00:00+03:00,28647.0,700831.0,962.0
|
| 606 |
+
604,2021-10-11 00:00:00+03:00,29409.0,713823.0,957.0
|
| 607 |
+
605,2021-10-12 00:00:00+03:00,28190.0,720334.0,973.0
|
| 608 |
+
606,2021-10-13 00:00:00+03:00,28717.0,726266.0,984.0
|
| 609 |
+
607,2021-10-14 00:00:00+03:00,31299.0,734909.0,986.0
|
| 610 |
+
608,2021-10-15 00:00:00+03:00,32196.0,743839.0,998.0
|
| 611 |
+
609,2021-10-16 00:00:00+03:00,33208.0,754162.0,1002.0
|
| 612 |
+
610,2021-10-17 00:00:00+03:00,34303.0,768751.0,997.0
|
| 613 |
+
611,2021-10-18 00:00:00+03:00,34325.0,785647.0,998.0
|
| 614 |
+
612,2021-10-19 00:00:00+03:00,33740.0,794946.0,1015.0
|
| 615 |
+
613,2021-10-20 00:00:00+03:00,34073.0,802760.0,1028.0
|
| 616 |
+
614,2021-10-21 00:00:00+03:00,36339.0,812168.0,1036.0
|
| 617 |
+
615,2021-10-22 00:00:00+03:00,37141.0,822792.0,1064.0
|
| 618 |
+
616,2021-10-23 00:00:00+03:00,37678.0,833318.0,1075.0
|
| 619 |
+
617,2021-10-24 00:00:00+03:00,35660.0,845122.0,1072.0
|
| 620 |
+
618,2021-10-25 00:00:00+03:00,37930.0,861293.0,1069.0
|
| 621 |
+
619,2021-10-26 00:00:00+03:00,36446.0,869660.0,1106.0
|
| 622 |
+
620,2021-10-27 00:00:00+03:00,36582.0,875968.0,1123.0
|
| 623 |
+
621,2021-10-28 00:00:00+03:00,40096.0,885587.0,1159.0
|
| 624 |
+
622,2021-10-29 00:00:00+03:00,39849.0,893811.0,1163.0
|
| 625 |
+
623,2021-10-30 00:00:00+03:00,40251.0,903993.0,1160.0
|
| 626 |
+
624,2021-10-31 00:00:00+03:00,40993.0,916713.0,1158.0
|
| 627 |
+
625,2021-11-01 00:00:00+03:00,40402.0,932773.0,1155.0
|
| 628 |
+
626,2021-11-02 00:00:00+03:00,39008.0,939698.0,1178.0
|
| 629 |
+
627,2021-11-03 00:00:00+03:00,40443.0,946145.0,1189.0
|
| 630 |
+
628,2021-11-04 00:00:00+03:00,40217.0,953239.0,1195.0
|
| 631 |
+
629,2021-11-05 00:00:00+03:00,40735.0,964177.0,1192.0
|
| 632 |
+
630,2021-11-06 00:00:00+03:00,41335.0,975123.0,1188.0
|
| 633 |
+
631,2021-11-07 00:00:00+03:00,39165.0,986303.0,1179.0
|
| 634 |
+
632,2021-11-08 00:00:00+03:00,39400.0,998931.0,1190.0
|
| 635 |
+
633,2021-11-09 00:00:00+03:00,39160.0,1004844.0,1211.0
|
| 636 |
+
634,2021-11-10 00:00:00+03:00,38058.0,1007098.0,1239.0
|
| 637 |
+
635,2021-11-11 00:00:00+03:00,40759.0,1013464.0,1237.0
|
| 638 |
+
636,2021-11-12 00:00:00+03:00,40123.0,1018707.0,1235.0
|
| 639 |
+
637,2021-11-13 00:00:00+03:00,39256.0,1022920.0,1241.0
|
| 640 |
+
638,2021-11-14 00:00:00+03:00,38823.0,1030703.0,1219.0
|
| 641 |
+
639,2021-11-15 00:00:00+03:00,38420.0,1040210.0,1211.0
|
| 642 |
+
640,2021-11-16 00:00:00+03:00,36818.0,1041627.0,1240.0
|
| 643 |
+
641,2021-11-17 00:00:00+03:00,36626.0,1040618.0,1247.0
|
| 644 |
+
642,2021-11-18 00:00:00+03:00,37374.0,1040327.0,1251.0
|
| 645 |
+
643,2021-11-19 00:00:00+03:00,37156.0,1039225.0,1254.0
|
| 646 |
+
644,2021-11-20 00:00:00+03:00,37120.0,1038919.0,1254.0
|
| 647 |
+
645,2021-11-21 00:00:00+03:00,36970.0,1042133.0,1252.0
|
| 648 |
+
646,2021-11-22 00:00:00+03:00,35681.0,1047860.0,1241.0
|
| 649 |
+
647,2021-11-23 00:00:00+03:00,33996.0,1044562.0,1243.0
|
| 650 |
+
648,2021-11-24 00:00:00+03:00,33558.0,1040198.0,1240.0
|
| 651 |
+
649,2021-11-25 00:00:00+03:00,33796.0,1034306.0,1238.0
|
| 652 |
+
650,2021-11-26 00:00:00+03:00,34690.0,1031616.0,1235.0
|
| 653 |
+
651,2021-11-27 00:00:00+03:00,33946.0,1027829.0,1239.0
|
| 654 |
+
652,2021-11-28 00:00:00+03:00,33548.0,1029507.0,1224.0
|
| 655 |
+
653,2021-11-29 00:00:00+03:00,33860.0,1034458.0,1209.0
|
| 656 |
+
654,2021-11-30 00:00:00+03:00,32648.0,1032435.0,1229.0
|
| 657 |
+
655,2021-12-01 00:00:00+03:00,32837.0,1028367.0,1226.0
|
| 658 |
+
656,2021-12-02 00:00:00+03:00,33389.0,1025350.0,1221.0
|
| 659 |
+
657,2021-12-03 00:00:00+03:00,32930.0,1020549.0,1217.0
|
| 660 |
+
658,2021-12-04 00:00:00+03:00,32974.0,1017126.0,1215.0
|
| 661 |
+
659,2021-12-05 00:00:00+03:00,32602.0,1017929.0,1206.0
|
| 662 |
+
660,2021-12-06 00:00:00+03:00,32136.0,1020811.0,1184.0
|
| 663 |
+
661,2021-12-07 00:00:00+03:00,31096.0,1016110.0,1182.0
|
| 664 |
+
662,2021-12-08 00:00:00+03:00,30752.0,1008707.0,1179.0
|
| 665 |
+
663,2021-12-09 00:00:00+03:00,30209.0,1001941.0,1181.0
|
| 666 |
+
664,2021-12-10 00:00:00+03:00,30873.0,995981.0,1176.0
|
| 667 |
+
665,2021-12-11 00:00:00+03:00,30288.0,988652.0,1171.0
|
| 668 |
+
666,2021-12-12 00:00:00+03:00,29929.0,986058.0,1132.0
|
| 669 |
+
667,2021-12-13 00:00:00+03:00,29558.0,985934.0,1121.0
|
| 670 |
+
668,2021-12-14 00:00:00+03:00,28343.0,979048.0,1145.0
|
| 671 |
+
669,2021-12-15 00:00:00+03:00,28363.0,970636.0,1142.0
|
| 672 |
+
670,2021-12-16 00:00:00+03:00,28486.0,960834.0,1133.0
|
| 673 |
+
671,2021-12-17 00:00:00+03:00,27743.0,950060.0,1080.0
|
| 674 |
+
672,2021-12-18 00:00:00+03:00,27434.0,938377.0,1076.0
|
| 675 |
+
673,2021-12-19 00:00:00+03:00,27967.0,932666.0,1023.0
|
| 676 |
+
674,2021-12-20 00:00:00+03:00,27022.0,928610.0,1019.0
|
| 677 |
+
675,2021-12-21 00:00:00+03:00,25907.0,913271.0,1027.0
|
| 678 |
+
676,2021-12-22 00:00:00+03:00,25264.0,895193.0,1020.0
|
| 679 |
+
677,2021-12-23 00:00:00+03:00,25667.0,878213.0,1002.0
|
| 680 |
+
678,2021-12-24 00:00:00+03:00,24703.0,860705.0,998.0
|
| 681 |
+
679,2021-12-25 00:00:00+03:00,24946.0,842563.0,981.0
|
| 682 |
+
680,2021-12-26 00:00:00+03:00,23721.0,828031.0,968.0
|
| 683 |
+
681,2021-12-27 00:00:00+03:00,23210.0,816589.0,937.0
|
| 684 |
+
682,2021-12-28 00:00:00+03:00,21922.0,793615.0,935.0
|
| 685 |
+
683,2021-12-29 00:00:00+03:00,21119.0,771026.0,932.0
|
| 686 |
+
684,2021-12-30 00:00:00+03:00,21073.0,748169.0,926.0
|
| 687 |
+
685,2021-12-31 00:00:00+03:00,20638.0,727203.0,912.0
|
| 688 |
+
686,2022-01-01 00:00:00+03:00,19751.0,712963.0,847.0
|
| 689 |
+
687,2022-01-02 00:00:00+03:00,18233.0,703409.0,811.0
|
| 690 |
+
688,2022-01-03 00:00:00+03:00,16343.0,694880.0,835.0
|
| 691 |
+
689,2022-01-04 00:00:00+03:00,15903.0,682878.0,834.0
|
| 692 |
+
690,2022-01-05 00:00:00+03:00,15772.0,672241.0,828.0
|
| 693 |
+
691,2022-01-06 00:00:00+03:00,15316.0,663806.0,802.0
|
| 694 |
+
692,2022-01-07 00:00:00+03:00,16735.0,657719.0,787.0
|
| 695 |
+
693,2022-01-08 00:00:00+03:00,16568.0,653042.0,796.0
|
| 696 |
+
694,2022-01-09 00:00:00+03:00,16246.0,647774.0,763.0
|
| 697 |
+
695,2022-01-10 00:00:00+03:00,15830.0,642973.0,741.0
|
| 698 |
+
696,2022-01-11 00:00:00+03:00,17525.0,634499.0,783.0
|
| 699 |
+
697,2022-01-12 00:00:00+03:00,17946.0,625354.0,745.0
|
| 700 |
+
698,2022-01-13 00:00:00+03:00,21155.0,619785.0,740.0
|
| 701 |
+
699,2022-01-14 00:00:00+03:00,23820.0,617914.0,739.0
|
| 702 |
+
700,2022-01-15 00:00:00+03:00,27179.0,617786.0,723.0
|
| 703 |
+
701,2022-01-16 00:00:00+03:00,29230.0,623599.0,686.0
|
| 704 |
+
702,2022-01-17 00:00:00+03:00,30726.0,633899.0,670.0
|
| 705 |
+
703,2022-01-18 00:00:00+03:00,31252.0,639899.0,688.0
|
| 706 |
+
704,2022-01-19 00:00:00+03:00,33899.0,650180.0,698.0
|
| 707 |
+
705,2022-01-20 00:00:00+03:00,38850.0,663868.0,684.0
|
| 708 |
+
706,2022-01-21 00:00:00+03:00,49513.0,687970.0,692.0
|
| 709 |
+
707,2022-01-22 00:00:00+03:00,49485.82,718976.0,681.0
|
| 710 |
+
708,2022-01-23 00:00:00+03:00,49458.64,758457.0,679.0
|
| 711 |
+
709,2022-01-24 00:00:00+03:00,49431.46,801197.0,655.0
|
| 712 |
+
710,2022-01-25 00:00:00+03:00,49404.28,841921.0,681.0
|
| 713 |
+
711,2022-01-26 00:00:00+03:00,49377.1,887759.0,657.0
|
| 714 |
+
712,2022-01-27 00:00:00+03:00,49349.92,946156.0,665.0
|
| 715 |
+
713,2022-01-28 00:00:00+03:00,49322.74,1014017.0,673.0
|
| 716 |
+
714,2022-01-29 00:00:00+03:00,49295.56,1014783.3,668.0
|
| 717 |
+
715,2022-01-30 00:00:00+03:00,49268.38,1015549.6,617.0
|
| 718 |
+
716,2022-01-31 00:00:00+03:00,49241.2,1016315.9,621.0
|
| 719 |
+
717,2022-02-01 00:00:00+03:00,49214.02,1017082.2,663.0
|
| 720 |
+
718,2022-02-02 00:00:00+03:00,49186.84,1017848.5,678.0
|
| 721 |
+
719,2022-02-03 00:00:00+03:00,49159.66,1018614.8,667.0
|
| 722 |
+
720,2022-02-04 00:00:00+03:00,49132.48,1019381.1,682.0
|
| 723 |
+
721,2022-02-05 00:00:00+03:00,49105.3,1020147.4,714.0
|
| 724 |
+
722,2022-02-06 00:00:00+03:00,49078.12,1020913.7,661.0
|
| 725 |
+
723,2022-02-07 00:00:00+03:00,49050.94,1021680.0,609.0
|
| 726 |
+
724,2022-02-08 00:00:00+03:00,49023.76,1022446.3,698.0
|
| 727 |
+
725,2022-02-09 00:00:00+03:00,48996.58,1023212.6,669.0
|
| 728 |
+
726,2022-02-10 00:00:00+03:00,48969.4,1023978.9,701.0
|
| 729 |
+
727,2022-02-11 00:00:00+03:00,48942.22,1024745.2,722.0
|
| 730 |
+
728,2022-02-12 00:00:00+03:00,48915.04,1025511.5,729.0
|
| 731 |
+
729,2022-02-13 00:00:00+03:00,48887.86,1026277.8,706.0
|
| 732 |
+
730,2022-02-14 00:00:00+03:00,48860.68,1027044.1,683.0
|
| 733 |
+
731,2022-02-15 00:00:00+03:00,48833.5,1027810.4,704.0
|
| 734 |
+
732,2022-02-16 00:00:00+03:00,48806.32,1028576.7,748.0
|
| 735 |
+
733,2022-02-17 00:00:00+03:00,48779.14,1029343.0,790.0
|
| 736 |
+
734,2022-02-18 00:00:00+03:00,48751.96,1030109.3,784.0
|
| 737 |
+
735,2022-02-19 00:00:00+03:00,48724.78,1030875.6,798.0
|
| 738 |
+
736,2022-02-20 00:00:00+03:00,48697.6,1031641.9,745.0
|
| 739 |
+
737,2022-02-21 00:00:00+03:00,48670.42,1032408.2,735.0
|
| 740 |
+
738,2022-02-22 00:00:00+03:00,48643.24,1033174.5,796.0
|
| 741 |
+
739,2022-02-23 00:00:00+03:00,48616.06,1033940.8,785.0
|
| 742 |
+
740,2022-02-24 00:00:00+03:00,48588.88,1034707.1,762.0
|
| 743 |
+
741,2022-02-25 00:00:00+03:00,48561.7,1035473.4,787.0
|
| 744 |
+
742,2022-02-26 00:00:00+03:00,48534.52,1036239.7,793.0
|
| 745 |
+
743,2022-02-27 00:00:00+03:00,48507.34,1037006.0,769.0
|
| 746 |
+
744,2022-02-28 00:00:00+03:00,48480.16,1037772.3,733.0
|
| 747 |
+
745,2022-03-01 00:00:00+03:00,48452.98,1038538.6,786.0
|
| 748 |
+
746,2022-03-02 00:00:00+03:00,48425.8,1039304.9,784.0
|
| 749 |
+
747,2022-03-03 00:00:00+03:00,48398.62,1040071.2,781.0
|
| 750 |
+
748,2022-03-04 00:00:00+03:00,48371.44,1040837.5,776.0
|
| 751 |
+
749,2022-03-05 00:00:00+03:00,48344.26,1041603.8,750.0
|
| 752 |
+
750,2022-03-06 00:00:00+03:00,48317.08,1042370.1,744.0
|
| 753 |
+
751,2022-03-07 00:00:00+03:00,48289.9,1043136.4,668.0
|
| 754 |
+
752,2022-03-08 00:00:00+03:00,48262.72,1043902.7,652.0
|
| 755 |
+
753,2022-03-09 00:00:00+03:00,48235.54,1044669.0,645.0
|
| 756 |
+
754,2022-03-10 00:00:00+03:00,48208.36,1045435.3,665.0
|
| 757 |
+
755,2022-03-11 00:00:00+03:00,48181.18,1046201.6,674.0
|
| 758 |
+
756,2022-03-12 00:00:00+03:00,48154.0,1046967.9,630.0
|
| 759 |
+
757,2022-03-13 00:00:00+03:00,44989.0,1047734.2,596.0
|
| 760 |
+
758,2022-03-14 00:00:00+03:00,41055.0,1048500.5,533.0
|
| 761 |
+
759,2022-03-15 00:00:00+03:00,36678.0,1049266.8,558.0
|
| 762 |
+
760,2022-03-16 00:00:00+03:00,36519.0,1050033.1,576.0
|
| 763 |
+
761,2022-03-17 00:00:00+03:00,34819.0,1050799.4,561.0
|
| 764 |
+
762,2022-03-18 00:00:00+03:00,34442.0,1051565.7,524.0
|
| 765 |
+
763,2022-03-19 00:00:00+03:00,32958.0,1052332.0,495.0
|
| 766 |
+
764,2022-03-20 00:00:00+03:00,31035.0,1008258.0,434.0
|
| 767 |
+
765,2022-03-21 00:00:00+03:00,28709.0,974620.0,409.0
|
| 768 |
+
766,2022-03-22 00:00:00+03:00,26394.0,925622.0,472.0
|
| 769 |
+
767,2022-03-23 00:00:00+03:00,26826.0,881397.0,429.0
|
| 770 |
+
768,2022-03-24 00:00:00+03:00,25387.0,839890.0,418.0
|
| 771 |
+
769,2022-03-25 00:00:00+03:00,25382.0,803014.0,398.0
|
| 772 |
+
770,2022-03-26 00:00:00+03:00,24072.0,765758.0,395.0
|
| 773 |
+
771,2022-03-27 00:00:00+03:00,23280.0,741160.0,338.0
|
| 774 |
+
772,2022-03-28 00:00:00+03:00,21101.0,726180.0,335.0
|
| 775 |
+
773,2022-03-29 00:00:00+03:00,19660.0,698272.0,339.0
|
| 776 |
+
774,2022-03-30 00:00:00+03:00,20145.0,666980.0,352.0
|
| 777 |
+
775,2022-03-31 00:00:00+03:00,19277.0,635416.0,345.0
|
| 778 |
+
776,2022-04-01 00:00:00+03:00,19164.0,608240.0,342.0
|
| 779 |
+
777,2022-04-02 00:00:00+03:00,17949.0,581302.0,340.0
|
| 780 |
+
778,2022-04-03 00:00:00+03:00,16828.0,562131.0,304.0
|
| 781 |
+
779,2022-04-04 00:00:00+03:00,15291.0,544285.0,287.0
|
| 782 |
+
780,2022-04-05 00:00:00+03:00,13947.0,520457.0,316.0
|
| 783 |
+
781,2022-04-06 00:00:00+03:00,14661.0,499521.0,291.0
|
| 784 |
+
782,2022-04-07 00:00:00+03:00,14355.0,478285.0,287.0
|
| 785 |
+
783,2022-04-08 00:00:00+03:00,14311.0,454632.0,280.0
|
| 786 |
+
784,2022-04-09 00:00:00+03:00,13573.0,427817.0,288.0
|
| 787 |
+
785,2022-04-10 00:00:00+03:00,13056.0,411242.0,259.0
|
| 788 |
+
786,2022-04-11 00:00:00+03:00,11855.0,396094.0,248.0
|
| 789 |
+
787,2022-04-12 00:00:00+03:00,10910.0,375452.0,281.0
|
| 790 |
+
788,2022-04-13 00:00:00+03:00,11754.0,358804.0,267.0
|
| 791 |
+
789,2022-04-14 00:00:00+03:00,11348.0,348045.0,254.0
|
| 792 |
+
790,2022-04-15 00:00:00+03:00,11432.0,339693.0,261.0
|
| 793 |
+
791,2022-04-16 00:00:00+03:00,11095.0,331542.0,240.0
|
| 794 |
+
792,2022-04-17 00:00:00+03:00,10263.0,325076.0,233.0
|
| 795 |
+
793,2022-04-18 00:00:00+03:00,9434.0,319973.0,213.0
|
| 796 |
+
794,2022-04-19 00:00:00+03:00,8640.0,311615.0,235.0
|
| 797 |
+
795,2022-04-20 00:00:00+03:00,9195.0,304387.0,223.0
|
| 798 |
+
796,2022-04-21 00:00:00+03:00,8875.0,298883.0,197.0
|
| 799 |
+
797,2022-04-22 00:00:00+03:00,9001.0,294209.0,195.0
|
| 800 |
+
798,2022-04-23 00:00:00+03:00,8829.0,289837.0,171.0
|
| 801 |
+
799,2022-04-24 00:00:00+03:00,8446.0,287607.0,168.0
|
| 802 |
+
800,2022-04-25 00:00:00+03:00,7651.0,286244.0,159.0
|
| 803 |
+
801,2022-04-26 00:00:00+03:00,7107.0,281276.0,176.0
|
| 804 |
+
802,2022-04-27 00:00:00+03:00,7705.0,277341.0,163.0
|
| 805 |
+
803,2022-04-28 00:00:00+03:00,7681.0,273793.0,166.0
|
| 806 |
+
804,2022-04-29 00:00:00+03:00,7710.0,270301.0,161.0
|
| 807 |
+
805,2022-04-30 00:00:00+03:00,7363.0,266485.0,157.0
|
| 808 |
+
806,2022-05-01 00:00:00+03:00,7047.0,264652.0,147.0
|
| 809 |
+
807,2022-05-02 00:00:00+03:00,6207.0,263221.0,136.0
|
| 810 |
+
808,2022-05-03 00:00:00+03:00,5466.0,261510.0,125.0
|
| 811 |
+
809,2022-05-04 00:00:00+03:00,5093.0,259810.0,129.0
|
| 812 |
+
810,2022-05-05 00:00:00+03:00,5011.0,255959.0,139.0
|
| 813 |
+
811,2022-05-06 00:00:00+03:00,5541.0,251956.0,136.0
|
| 814 |
+
812,2022-05-07 00:00:00+03:00,5500.0,248675.0,132.0
|
| 815 |
+
813,2022-05-08 00:00:00+03:00,5447.0,247322.0,118.0
|
| 816 |
+
814,2022-05-09 00:00:00+03:00,5030.0,246290.0,103.0
|
| 817 |
+
815,2022-05-10 00:00:00+03:00,4531.0,245706.0,101.0
|
| 818 |
+
816,2022-05-11 00:00:00+03:00,4102.0,244667.0,98.0
|
| 819 |
+
817,2022-05-12 00:00:00+03:00,4065.0,241691.0,111.0
|
| 820 |
+
818,2022-05-13 00:00:00+03:00,4896.0,239225.0,105.0
|
| 821 |
+
819,2022-05-14 00:00:00+03:00,5047.0,236787.0,107.0
|
requirements.txt
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
|
|
| 1 |
pandas
|
| 2 |
numpy
|
| 3 |
-
streamlit
|
| 4 |
-
pytz
|
| 5 |
plotly
|
| 6 |
statsmodels
|
| 7 |
-
scikit-learn
|
| 8 |
-
matplotlib
|
| 9 |
-
pdfkit
|
| 10 |
scipy
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
streamlit
|
| 2 |
pandas
|
| 3 |
numpy
|
|
|
|
|
|
|
| 4 |
plotly
|
| 5 |
statsmodels
|
|
|
|
|
|
|
|
|
|
| 6 |
scipy
|
| 7 |
+
scikit-learn
|
| 8 |
+
pytz
|
| 9 |
+
pmdarima
|
| 10 |
+
arch
|
| 11 |
+
prophet # если хотите Prophet (fbprophet -> prophet)
|
| 12 |
+
lightgbm
|
| 13 |
+
xgboost
|
| 14 |
+
torch
|
| 15 |
+
tensorflow # альтернативно для Keras
|
| 16 |
+
tbats # если нужен TBATS
|
| 17 |
+
autogluon.timeseries # для AutoGluon (очень тяжёлый)
|
src/lab3_functions.py
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# TimeSeriesHomework/src/lab3_functions.py
|
| 2 |
+
"""
|
| 3 |
+
Набор вспомогательных функций для ЛР3:
|
| 4 |
+
- обёртки для SARIMAX, auto_arima (pmdarima), VAR, GARCH (arch) и т.п.
|
| 5 |
+
- forecast helpers
|
| 6 |
+
- простые метрики
|
| 7 |
+
Файл не использует абсолютных путей и предназначен для импорта в проекте.
|
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import warnings
|
| 11 |
+
warnings.filterwarnings("ignore")
|
| 12 |
+
|
| 13 |
+
from typing import Tuple, Dict, Any, Optional, List
|
| 14 |
+
import numpy as np
|
| 15 |
+
import pandas as pd
|
| 16 |
+
|
| 17 |
+
# optional heavy deps
|
| 18 |
+
try:
|
| 19 |
+
import pmdarima as pm
|
| 20 |
+
PM_AVAILABLE = True
|
| 21 |
+
except Exception:
|
| 22 |
+
PM_AVAILABLE = False
|
| 23 |
+
|
| 24 |
+
try:
|
| 25 |
+
from statsmodels.tsa.statespace.sarimax import SARIMAX
|
| 26 |
+
from statsmodels.tsa.api import VAR
|
| 27 |
+
STATSMODELS_AVAILABLE = True
|
| 28 |
+
except Exception:
|
| 29 |
+
STATSMODELS_AVAILABLE = False
|
| 30 |
+
|
| 31 |
+
try:
|
| 32 |
+
from arch import arch_model
|
| 33 |
+
ARCH_AVAILABLE = True
|
| 34 |
+
except Exception:
|
| 35 |
+
ARCH_AVAILABLE = False
|
| 36 |
+
|
| 37 |
+
# sklearn metrics used for convenience (optional)
|
| 38 |
+
try:
|
| 39 |
+
from sklearn.metrics import mean_absolute_error, mean_squared_error
|
| 40 |
+
SKLEARN_AVAILABLE = True
|
| 41 |
+
except Exception:
|
| 42 |
+
SKLEARN_AVAILABLE = False
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def is_pandas_series(x: Any) -> bool:
|
| 46 |
+
return isinstance(x, (pd.Series,))
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def mae_rmse(y_true, y_pred) -> Dict[str, float]:
|
| 50 |
+
y_true = np.array(y_true)
|
| 51 |
+
y_pred = np.array(y_pred)
|
| 52 |
+
if SKLEARN_AVAILABLE:
|
| 53 |
+
mae = float(mean_absolute_error(y_true, y_pred))
|
| 54 |
+
rmse = float(np.sqrt(mean_squared_error(y_true, y_pred)))
|
| 55 |
+
else:
|
| 56 |
+
mae = float(np.mean(np.abs(y_true - y_pred)))
|
| 57 |
+
rmse = float(np.sqrt(np.mean((y_true - y_pred) ** 2)))
|
| 58 |
+
return {"MAE": mae, "RMSE": rmse}
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def fit_auto_arima(series: pd.Series, seasonal: bool = False, m: int = 1, **kwargs):
|
| 62 |
+
"""
|
| 63 |
+
Подбор ARIMA через pmdarima.auto_arima. Возвращает обученную модель pmdarima.
|
| 64 |
+
"""
|
| 65 |
+
if not PM_AVAILABLE:
|
| 66 |
+
raise ImportError("pmdarima не установлен. Установите pmdarima (pip install pmdarima).")
|
| 67 |
+
if not is_pandas_series(series):
|
| 68 |
+
series = pd.Series(series)
|
| 69 |
+
series_clean = series.dropna()
|
| 70 |
+
if series_clean.empty:
|
| 71 |
+
raise ValueError("Пустая серия передана в fit_auto_arima.")
|
| 72 |
+
model = pm.auto_arima(series_clean, seasonal=seasonal, m=m, error_action="ignore", suppress_warnings=True, **kwargs)
|
| 73 |
+
return model
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def fit_sarimax(series: pd.Series, order: Tuple[int, int, int] = (1, 0, 0),
|
| 77 |
+
seasonal_order: Tuple[int, int, int, int] = (0, 0, 0, 0),
|
| 78 |
+
enforce_stationarity: bool = False, enforce_invertibility: bool = True, **fit_kwargs):
|
| 79 |
+
"""
|
| 80 |
+
Обучает SARIMAX (statsmodels). Возвращает результат fit() (SARIMAXResults).
|
| 81 |
+
"""
|
| 82 |
+
if not STATSMODELS_AVAILABLE:
|
| 83 |
+
raise ImportError("statsmodels не установлен. Установите statsmodels.")
|
| 84 |
+
if not is_pandas_series(series):
|
| 85 |
+
series = pd.Series(series)
|
| 86 |
+
series_clean = series.dropna()
|
| 87 |
+
if series_clean.empty:
|
| 88 |
+
raise ValueError("Пустая серия передана в fit_sarimax.")
|
| 89 |
+
model = SARIMAX(series_clean, order=order, seasonal_order=seasonal_order,
|
| 90 |
+
enforce_stationarity=enforce_stationarity, enforce_invertibility=enforce_invertibility)
|
| 91 |
+
res = model.fit(disp=False, **fit_kwargs)
|
| 92 |
+
return res
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def forecast_sarimax(fit_res, steps: int, alpha: float = 0.05) -> Tuple[np.ndarray, Tuple[np.ndarray, np.ndarray]]:
|
| 96 |
+
"""
|
| 97 |
+
Делает прогноз из обученного SARIMAX-результата (res.get_forecast).
|
| 98 |
+
Возвращает (mean, (lower, upper)) — numpy arrays длины steps.
|
| 99 |
+
"""
|
| 100 |
+
if hasattr(fit_res, "get_forecast"):
|
| 101 |
+
fc = fit_res.get_forecast(steps=steps)
|
| 102 |
+
mean = np.asarray(fc.predicted_mean)
|
| 103 |
+
try:
|
| 104 |
+
conf = fc.conf_int(alpha=alpha)
|
| 105 |
+
lower = np.asarray(conf.iloc[:, 0])
|
| 106 |
+
upper = np.asarray(conf.iloc[:, 1])
|
| 107 |
+
except Exception:
|
| 108 |
+
lower = np.full(len(mean), np.nan)
|
| 109 |
+
upper = np.full(len(mean), np.nan)
|
| 110 |
+
return mean, (lower, upper)
|
| 111 |
+
else:
|
| 112 |
+
# fallback на forecast
|
| 113 |
+
try:
|
| 114 |
+
f = fit_res.forecast(steps=steps)
|
| 115 |
+
mean = np.asarray(f)
|
| 116 |
+
lower = np.full(len(mean), np.nan)
|
| 117 |
+
upper = np.full(len(mean), np.nan)
|
| 118 |
+
return mean, (lower, upper)
|
| 119 |
+
except Exception as e:
|
| 120 |
+
raise ValueError(f"Не удалось получить прогноз из объекта результата: {e}")
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
def fit_var(df: pd.DataFrame, maxlags: int = 15):
|
| 124 |
+
"""
|
| 125 |
+
Обучает VAR на multivariate dataframe (pandas DataFrame). Возвращает fitted VARResults.
|
| 126 |
+
"""
|
| 127 |
+
if not STATSMODELS_AVAILABLE:
|
| 128 |
+
raise ImportError("statsmodels не установлен. Установите statsmodels.")
|
| 129 |
+
if not isinstance(df, pd.DataFrame):
|
| 130 |
+
raise ValueError("fit_var ожидает pd.DataFrame с несколькими числовыми колонками.")
|
| 131 |
+
df_clean = df.dropna()
|
| 132 |
+
if df_clean.shape[0] < 3:
|
| 133 |
+
raise ValueError("Недостаточно наблюдений для VAR.")
|
| 134 |
+
model = VAR(df_clean)
|
| 135 |
+
sel = model.select_order(maxlags=maxlags)
|
| 136 |
+
best_lag = None
|
| 137 |
+
try:
|
| 138 |
+
if hasattr(sel, "selected_orders"):
|
| 139 |
+
so = sel.selected_orders
|
| 140 |
+
for k in ("aic", "bic", "fpe", "hqic"):
|
| 141 |
+
val = so.get(k, None)
|
| 142 |
+
if val is not None:
|
| 143 |
+
best_lag = int(val)
|
| 144 |
+
break
|
| 145 |
+
except Exception:
|
| 146 |
+
best_lag = None
|
| 147 |
+
if best_lag is None or best_lag < 1:
|
| 148 |
+
best_lag = 1
|
| 149 |
+
fitted = model.fit(maxlags=best_lag)
|
| 150 |
+
return fitted
|
| 151 |
+
|
| 152 |
+
|
| 153 |
+
def forecast_var(fitted_var, steps: int) -> pd.DataFrame:
|
| 154 |
+
"""
|
| 155 |
+
Multi-step forecasting for VARResults. Возвращает DataFrame прогнозов (columns = variables).
|
| 156 |
+
"""
|
| 157 |
+
try:
|
| 158 |
+
forecast = fitted_var.forecast(fitted_var.endog[-fitted_var.k_ar:], steps=steps)
|
| 159 |
+
cols = fitted_var.names
|
| 160 |
+
idx = range(1, steps + 1)
|
| 161 |
+
return pd.DataFrame(forecast, columns=cols, index=idx)
|
| 162 |
+
except Exception as e:
|
| 163 |
+
raise ValueError(f"Ошибка при прогнозе VAR: {e}")
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def fit_garch(series: pd.Series, p: int = 1, q: int = 1):
|
| 167 |
+
"""
|
| 168 |
+
Обучает GARCH(p,q) (arch package). Возвращает объект результата fit() из arch.
|
| 169 |
+
"""
|
| 170 |
+
if not ARCH_AVAILABLE:
|
| 171 |
+
raise ImportError("arch не установлен. Установите arch (pip install arch).")
|
| 172 |
+
if not is_pandas_series(series):
|
| 173 |
+
series = pd.Series(series)
|
| 174 |
+
series_clean = series.dropna()
|
| 175 |
+
if series_clean.empty:
|
| 176 |
+
raise ValueError("Пустая серия передана в fit_garch.")
|
| 177 |
+
am = arch_model(series_clean, vol="Garch", p=p, q=q, dist="normal")
|
| 178 |
+
res = am.fit(disp="off")
|
| 179 |
+
return res
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def safe_summary(obj) -> str:
|
| 183 |
+
try:
|
| 184 |
+
return str(obj.summary())
|
| 185 |
+
except Exception:
|
| 186 |
+
return repr(obj)
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
# краткий тест при запуске модуля напрямую
|
| 190 |
+
if __name__ == "__main__":
|
| 191 |
+
print("lab3_functions: доступные функции:",
|
| 192 |
+
[n for n in dir() if n.startswith("fit_") or n.startswith("forecast_")])
|
src/lab3_pipeline.py
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# TimeSeriesHomework/src/lab3_pipeline.py
|
| 2 |
+
"""
|
| 3 |
+
lab3_pipeline.py
|
| 4 |
+
Простой воспроизводимый pipeline для ЛР №3:
|
| 5 |
+
- загрузка CSV/Parquet
|
| 6 |
+
- предобработка / ресемплинг
|
| 7 |
+
- Box-Cox / log (если возможно)
|
| 8 |
+
- тесты стационарности (ADF, KPSS)
|
| 9 |
+
- создание лагов / роллов
|
| 10 |
+
- простые модели (Naive, SeasonalNaive, SARIMAX, auto_arima если доступен)
|
| 11 |
+
- VAR если мультивариатные данные
|
| 12 |
+
- генерация простого HTML-отчёта
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
import argparse
|
| 16 |
+
import os
|
| 17 |
+
import math
|
| 18 |
+
import time
|
| 19 |
+
from typing import Tuple, Dict, Any, Optional, List
|
| 20 |
+
|
| 21 |
+
import numpy as np
|
| 22 |
+
import pandas as pd
|
| 23 |
+
import matplotlib.pyplot as plt
|
| 24 |
+
|
| 25 |
+
# statsmodels (нужен для большинства тестов/моделей)
|
| 26 |
+
try:
|
| 27 |
+
from statsmodels.tsa.stattools import adfuller, kpss
|
| 28 |
+
from statsmodels.tsa.seasonal import seasonal_decompose
|
| 29 |
+
from statsmodels.stats.diagnostic import acorr_ljungbox
|
| 30 |
+
STATSMODELS_AVAILABLE = True
|
| 31 |
+
except Exception as e:
|
| 32 |
+
STATSMODELS_AVAILABLE = False
|
| 33 |
+
print("warning: statsmodels not available:", e)
|
| 34 |
+
|
| 35 |
+
# optional heavy deps
|
| 36 |
+
try:
|
| 37 |
+
import pmdarima as pm
|
| 38 |
+
PM_AVAILABLE = True
|
| 39 |
+
except Exception:
|
| 40 |
+
PM_AVAILABLE = False
|
| 41 |
+
|
| 42 |
+
try:
|
| 43 |
+
from scipy.stats import boxcox, boxcox_normmax
|
| 44 |
+
SCIPY_AVAILABLE = True
|
| 45 |
+
except Exception:
|
| 46 |
+
SCIPY_AVAILABLE = False
|
| 47 |
+
|
| 48 |
+
# ---- helpers / metrics ----
|
| 49 |
+
def mae(y_true, y_pred): return np.mean(np.abs(y_true - y_pred))
|
| 50 |
+
def rmse(y_true, y_pred): return math.sqrt(np.mean((y_true - y_pred)**2))
|
| 51 |
+
def mape(y_true, y_pred): return np.mean(np.abs((y_true - y_pred) / (y_true + 1e-9))) * 100.0
|
| 52 |
+
def smape(y_true, y_pred): return 100.0 * np.mean(2.0 * np.abs(y_pred - y_true) / (np.abs(y_true) + np.abs(y_pred) + 1e-9))
|
| 53 |
+
|
| 54 |
+
# ---- IO / preprocessing ----
|
| 55 |
+
def load_data(path: str, timestamp_col: str = 'timestamp', tz: Optional[str] = None) -> pd.DataFrame:
|
| 56 |
+
if path.endswith('.parquet'):
|
| 57 |
+
df = pd.read_parquet(path)
|
| 58 |
+
else:
|
| 59 |
+
df = pd.read_csv(path)
|
| 60 |
+
if timestamp_col not in df.columns:
|
| 61 |
+
raise ValueError(f"timestamp column '{timestamp_col}' not found in data")
|
| 62 |
+
df[timestamp_col] = pd.to_datetime(df[timestamp_col], errors='coerce')
|
| 63 |
+
if tz is not None:
|
| 64 |
+
try:
|
| 65 |
+
df[timestamp_col] = df[timestamp_col].dt.tz_localize(tz)
|
| 66 |
+
except Exception:
|
| 67 |
+
try:
|
| 68 |
+
df[timestamp_col] = df[timestamp_col].dt.tz_convert(tz)
|
| 69 |
+
except Exception:
|
| 70 |
+
pass
|
| 71 |
+
df = df.sort_values(timestamp_col).drop_duplicates(subset=[timestamp_col])
|
| 72 |
+
df = df.set_index(timestamp_col)
|
| 73 |
+
return df
|
| 74 |
+
|
| 75 |
+
def resample_and_interpolate(df: pd.DataFrame, freq: str = 'D', method: str = 'linear') -> pd.DataFrame:
|
| 76 |
+
dfr = df.resample(freq).asfreq()
|
| 77 |
+
if method == 'linear':
|
| 78 |
+
return dfr.interpolate(method='linear')
|
| 79 |
+
elif method == 'ffill':
|
| 80 |
+
return dfr.fillna(method='ffill')
|
| 81 |
+
else:
|
| 82 |
+
return dfr.fillna(method='ffill').interpolate()
|
| 83 |
+
|
| 84 |
+
# ---- transforms ----
|
| 85 |
+
def apply_log(series: pd.Series):
|
| 86 |
+
if (series <= 0).any():
|
| 87 |
+
raise ValueError("log transform requires positive values")
|
| 88 |
+
return np.log(series)
|
| 89 |
+
|
| 90 |
+
def apply_boxcox(series: pd.Series, lmbda: Optional[float] = None):
|
| 91 |
+
if not SCIPY_AVAILABLE:
|
| 92 |
+
raise ImportError("scipy required for boxcox transformations")
|
| 93 |
+
s = series.dropna()
|
| 94 |
+
if (s <= 0).any():
|
| 95 |
+
raise ValueError("Box-Cox requires positive values")
|
| 96 |
+
if lmbda is None:
|
| 97 |
+
lmbda = boxcox_normmax(s, brack=(-2,2))
|
| 98 |
+
transformed = boxcox(s, lmbda)
|
| 99 |
+
out = pd.Series(index=s.index, data=transformed)
|
| 100 |
+
return out, lmbda
|
| 101 |
+
|
| 102 |
+
def difference(series: pd.Series, d=1):
|
| 103 |
+
return series.diff(d)
|
| 104 |
+
|
| 105 |
+
# ---- feature engineering ----
|
| 106 |
+
def make_lags(df: pd.DataFrame, col: str, lags: List[int]):
|
| 107 |
+
for l in lags:
|
| 108 |
+
df[f'{col}_lag_{l}'] = df[col].shift(l)
|
| 109 |
+
return df
|
| 110 |
+
|
| 111 |
+
def make_rolls(df: pd.DataFrame, col: str, windows: List[int]):
|
| 112 |
+
for w in windows:
|
| 113 |
+
df[f'{col}_roll_mean_{w}'] = df[col].rolling(window=w, min_periods=1).mean()
|
| 114 |
+
df[f'{col}_roll_std_{w}'] = df[col].rolling(window=w, min_periods=1).std()
|
| 115 |
+
df[f'{col}_roll_min_{w}'] = df[col].rolling(window=w, min_periods=1).min()
|
| 116 |
+
df[f'{col}_roll_max_{w}'] = df[col].rolling(window=w, min_periods=1).max()
|
| 117 |
+
return df
|
| 118 |
+
|
| 119 |
+
def make_time_features(df: pd.DataFrame, index_name: Optional[str] = None):
|
| 120 |
+
idx = df.index if index_name is None else pd.to_datetime(df[index_name])
|
| 121 |
+
df['dayofweek'] = idx.dayofweek
|
| 122 |
+
df['month'] = idx.month
|
| 123 |
+
df['sin_week'] = np.sin(2 * np.pi * df['dayofweek'] / 7)
|
| 124 |
+
df['cos_month'] = np.cos(2 * np.pi * (df['month'] - 1) / 12)
|
| 125 |
+
return df
|
| 126 |
+
|
| 127 |
+
def chronological_split(df: pd.DataFrame, frac_train=0.7, frac_val=0.15):
|
| 128 |
+
n = len(df)
|
| 129 |
+
i_train = int(n * frac_train)
|
| 130 |
+
i_val = i_train + int(n * frac_val)
|
| 131 |
+
train = df.iloc[:i_train].copy()
|
| 132 |
+
val = df.iloc[i_train:i_val].copy()
|
| 133 |
+
test = df.iloc[i_val:].copy()
|
| 134 |
+
return train, val, test
|
| 135 |
+
|
| 136 |
+
# ---- simple models / wrappers ----
|
| 137 |
+
def naive_forecast(train: pd.Series, steps: int):
|
| 138 |
+
last = train.iloc[-1]
|
| 139 |
+
return np.full(steps, last)
|
| 140 |
+
|
| 141 |
+
def seasonal_naive_forecast(series: pd.Series, season: int, steps: int):
|
| 142 |
+
last = series.iloc[-season:]
|
| 143 |
+
reps = int(np.ceil(steps / season))
|
| 144 |
+
arr = np.tile(last.values, reps)[:steps]
|
| 145 |
+
return arr
|
| 146 |
+
|
| 147 |
+
def fit_sarimax_wrapper(series: pd.Series, order=(1,0,0), seasonal_order=(0,0,0,0), **kwargs):
|
| 148 |
+
if not STATSMODELS_AVAILABLE:
|
| 149 |
+
raise ImportError("statsmodels required for SARIMAX")
|
| 150 |
+
from statsmodels.tsa.statespace.sarimax import SARIMAX
|
| 151 |
+
m = SARIMAX(series.dropna(), order=order, seasonal_order=seasonal_order,
|
| 152 |
+
enforce_stationarity=False, enforce_invertibility=False)
|
| 153 |
+
res = m.fit(disp=False, **kwargs)
|
| 154 |
+
return res
|
| 155 |
+
|
| 156 |
+
def forecast_sarimax(fit_res, steps: int, alpha: float = 0.05):
|
| 157 |
+
if hasattr(fit_res, "get_forecast"):
|
| 158 |
+
fc = fit_res.get_forecast(steps=steps)
|
| 159 |
+
mean = np.asarray(fc.predicted_mean)
|
| 160 |
+
try:
|
| 161 |
+
conf = fc.conf_int(alpha=alpha)
|
| 162 |
+
lower = np.asarray(conf.iloc[:,0])
|
| 163 |
+
upper = np.asarray(conf.iloc[:,1])
|
| 164 |
+
except Exception:
|
| 165 |
+
lower = np.full(len(mean), np.nan)
|
| 166 |
+
upper = np.full(len(mean), np.nan)
|
| 167 |
+
return mean, (lower, upper)
|
| 168 |
+
else:
|
| 169 |
+
f = fit_res.forecast(steps=steps)
|
| 170 |
+
mean = np.asarray(f)
|
| 171 |
+
return mean, (np.full(len(mean), np.nan), np.full(len(mean), np.nan))
|
| 172 |
+
|
| 173 |
+
# ---- report generator ----
|
| 174 |
+
def generate_report_html(out_path: str, plots: List[plt.Figure], tables: Dict[str, pd.DataFrame], title="LR3 report"):
|
| 175 |
+
html_parts = [f"<html><head><meta charset='utf-8'><title>{title}</title></head><body><h1>{title}</h1>"]
|
| 176 |
+
for name, df in tables.items():
|
| 177 |
+
html_parts.append(f"<h2>{name}</h2>")
|
| 178 |
+
html_parts.append(df.to_html(classes='table table-striped', border=0))
|
| 179 |
+
for i, fig in enumerate(plots):
|
| 180 |
+
img_path = f"plot_{i}.png"
|
| 181 |
+
fig.savefig(img_path, bbox_inches='tight')
|
| 182 |
+
html_parts.append(f"<h3>Figure {i+1}</h3><img src='{img_path}' style='max-width:100%'>")
|
| 183 |
+
html_parts.append("</body></html>")
|
| 184 |
+
with open(out_path, 'w', encoding='utf-8') as f:
|
| 185 |
+
f.write("\n".join(html_parts))
|
| 186 |
+
print("Report saved to", out_path)
|
| 187 |
+
|
| 188 |
+
# ---- main pipeline ----
|
| 189 |
+
def run_pipeline(data_path: str, timestamp_col: str, target_col: str, out_report: str = 'lab3_report.html', freq='D'):
|
| 190 |
+
df = load_data(data_path, timestamp_col)
|
| 191 |
+
if target_col not in df.columns:
|
| 192 |
+
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
|
| 193 |
+
if not numeric_cols:
|
| 194 |
+
raise ValueError("No numeric columns found for target")
|
| 195 |
+
target_col = numeric_cols[0]
|
| 196 |
+
|
| 197 |
+
series = df[target_col].astype('float').copy()
|
| 198 |
+
series = resample_and_interpolate(series.to_frame(), freq=freq).iloc[:,0]
|
| 199 |
+
|
| 200 |
+
df_all = series.to_frame(name=target_col)
|
| 201 |
+
df_all = make_time_features(df_all)
|
| 202 |
+
df_all = make_lags(df_all, target_col, [1,2,7,30])
|
| 203 |
+
df_all = make_rolls(df_all, target_col, [7,30])
|
| 204 |
+
train, val, test = chronological_split(df_all, 0.7, 0.15)
|
| 205 |
+
y_train = train[target_col]
|
| 206 |
+
y_val = val[target_col]
|
| 207 |
+
y_test = test[target_col]
|
| 208 |
+
|
| 209 |
+
results = []
|
| 210 |
+
horizons = [1,7,30]
|
| 211 |
+
for h in horizons:
|
| 212 |
+
results.append({'model':'naive','h':h,'pred':naive_forecast(y_train,h)})
|
| 213 |
+
results.append({'model':'seasonal_naive','h':h,'pred':seasonal_naive_forecast(y_train, season=7, steps=h)})
|
| 214 |
+
|
| 215 |
+
# SARIMAX baseline
|
| 216 |
+
sarimax_res = None
|
| 217 |
+
try:
|
| 218 |
+
sarimax_res = fit_sarimax_wrapper(y_train, order=(1,1,1))
|
| 219 |
+
for h in horizons:
|
| 220 |
+
p, ci = forecast_sarimax(sarimax_res, steps=h)
|
| 221 |
+
results.append({'model':'sarimax(1,1,1)','h':h,'pred':p})
|
| 222 |
+
except Exception as e:
|
| 223 |
+
print("SARIMAX fit failed:", e)
|
| 224 |
+
|
| 225 |
+
# pmdarima auto_arima
|
| 226 |
+
if PM_AVAILABLE:
|
| 227 |
+
try:
|
| 228 |
+
auto = pm.auto_arima(y_train.dropna(), seasonal=False, error_action='ignore', suppress_warnings=True)
|
| 229 |
+
for h in horizons:
|
| 230 |
+
p = auto.predict(n_periods=h)
|
| 231 |
+
results.append({'model':'auto_arima','h':h,'pred':p})
|
| 232 |
+
except Exception as e:
|
| 233 |
+
print("auto_arima failed:", e)
|
| 234 |
+
|
| 235 |
+
# Evaluate
|
| 236 |
+
eval_tables = []
|
| 237 |
+
plots = []
|
| 238 |
+
for rec in results:
|
| 239 |
+
pred = np.asarray(rec['pred']).ravel()
|
| 240 |
+
y_true = y_test.values[:len(pred)]
|
| 241 |
+
if len(y_true)==0:
|
| 242 |
+
continue
|
| 243 |
+
eval_tables.append({
|
| 244 |
+
'model':rec['model'],
|
| 245 |
+
'h':rec['h'],
|
| 246 |
+
'MAE':mae(y_true,pred),
|
| 247 |
+
'RMSE':rmse(y_true,pred),
|
| 248 |
+
'MAPE':mape(y_true,pred),
|
| 249 |
+
'SMAPE':smape(y_true,pred)
|
| 250 |
+
})
|
| 251 |
+
fig, ax = plt.subplots(figsize=(8,3))
|
| 252 |
+
ax.plot(y_train.index[-100:], y_train.values[-100:], label='train')
|
| 253 |
+
ax.plot(y_test.index[:len(pred)], y_true, label='test')
|
| 254 |
+
ax.plot(y_test.index[:len(pred)], pred, label=f'pred_{rec["model"]}_h{rec["h"]}')
|
| 255 |
+
ax.legend()
|
| 256 |
+
plots.append(fig)
|
| 257 |
+
|
| 258 |
+
eval_df = pd.DataFrame(eval_tables)
|
| 259 |
+
tables = {'evaluation': eval_df}
|
| 260 |
+
generate_report_html(out_report, plots, tables, title="Lab3 Report")
|
| 261 |
+
print("Done. Report:", out_report)
|
| 262 |
+
|
| 263 |
+
# CLI runner
|
| 264 |
+
if __name__ == '__main__':
|
| 265 |
+
parser = argparse.ArgumentParser()
|
| 266 |
+
parser.add_argument('--data', required=True)
|
| 267 |
+
parser.add_argument('--timestamp', default='timestamp')
|
| 268 |
+
parser.add_argument('--target', default='target')
|
| 269 |
+
parser.add_argument('--out', default='lab3_report.html')
|
| 270 |
+
parser.add_argument('--freq', default='D')
|
| 271 |
+
args = parser.parse_args()
|
| 272 |
+
run_pipeline(args.data, args.timestamp, args.target, out_report=args.out, freq=args.freq)
|
src/lab4_functions.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# lab4_functions.py
|
| 2 |
+
"""
|
| 3 |
+
Простейший набор для ЛР №4:
|
| 4 |
+
- Feature engineering (lags, rolling)
|
| 5 |
+
- Обучение Ridge, Lasso, RandomForest, LightGBM (опционально)
|
| 6 |
+
- TimeSeriesSplit wrapper
|
| 7 |
+
"""
|
| 8 |
+
import numpy as np
|
| 9 |
+
import pandas as pd
|
| 10 |
+
from typing import List, Dict
|
| 11 |
+
from sklearn.linear_model import Ridge, Lasso
|
| 12 |
+
from sklearn.ensemble import RandomForestRegressor
|
| 13 |
+
from sklearn.model_selection import TimeSeriesSplit, cross_val_score
|
| 14 |
+
from sklearn.metrics import mean_absolute_error
|
| 15 |
+
import warnings
|
| 16 |
+
warnings.filterwarnings("ignore")
|
| 17 |
+
|
| 18 |
+
try:
|
| 19 |
+
import lightgbm as lgb
|
| 20 |
+
LGB_AVAILABLE = True
|
| 21 |
+
except Exception:
|
| 22 |
+
LGB_AVAILABLE = False
|
| 23 |
+
|
| 24 |
+
def make_lag_features(df: pd.DataFrame, target:str, lags:List[int]=[1,7,30]):
|
| 25 |
+
dfc = df.copy().set_index('timestamp').sort_index()
|
| 26 |
+
for l in lags:
|
| 27 |
+
dfc[f'{target}_lag_{l}'] = dfc[target].shift(l)
|
| 28 |
+
dfc = dfc.dropna().reset_index()
|
| 29 |
+
return dfc
|
| 30 |
+
|
| 31 |
+
def train_baselines(X_train, y_train):
|
| 32 |
+
models = {}
|
| 33 |
+
models['Ridge'] = Ridge().fit(X_train, y_train)
|
| 34 |
+
models['Lasso'] = Lasso().fit(X_train, y_train)
|
| 35 |
+
models['RF'] = RandomForestRegressor(n_estimators=100, random_state=42).fit(X_train, y_train)
|
| 36 |
+
if LGB_AVAILABLE:
|
| 37 |
+
models['LightGBM'] = lgb.LGBMRegressor(n_estimators=100).fit(X_train, y_train)
|
| 38 |
+
return models
|
| 39 |
+
|
| 40 |
+
def cv_score_ts(model, X, y, n_splits=5, scoring='neg_mean_absolute_error'):
|
| 41 |
+
tscv = TimeSeriesSplit(n_splits=n_splits)
|
| 42 |
+
scores = cross_val_score(model, X, y, cv=tscv, scoring=scoring)
|
| 43 |
+
return scores.mean()
|
src/lab5_functions.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# lab5_functions.py
|
| 2 |
+
"""
|
| 3 |
+
Минимальный LSTM example для ЛР №5 (PyTorch).
|
| 4 |
+
Если у вас нет torch — функции выбросят понятную ошибку.
|
| 5 |
+
"""
|
| 6 |
+
import numpy as np
|
| 7 |
+
import pandas as pd
|
| 8 |
+
|
| 9 |
+
try:
|
| 10 |
+
import torch
|
| 11 |
+
import torch.nn as nn
|
| 12 |
+
TORCH_AVAILABLE = True
|
| 13 |
+
except Exception:
|
| 14 |
+
TORCH_AVAILABLE = False
|
| 15 |
+
|
| 16 |
+
if TORCH_AVAILABLE:
|
| 17 |
+
class SimpleLSTM(nn.Module):
|
| 18 |
+
def __init__(self, input_size, hidden_size=64, num_layers=1, out_size=1):
|
| 19 |
+
super().__init__()
|
| 20 |
+
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
|
| 21 |
+
self.fc = nn.Linear(hidden_size, out_size)
|
| 22 |
+
def forward(self, x):
|
| 23 |
+
out, _ = self.lstm(x)
|
| 24 |
+
return self.fc(out[:, -1, :])
|
| 25 |
+
|
| 26 |
+
def create_sequences(series, lookback=30, horizon=1):
|
| 27 |
+
X, y = [], []
|
| 28 |
+
for i in range(len(series) - lookback - horizon + 1):
|
| 29 |
+
X.append(series[i:i+lookback])
|
| 30 |
+
y.append(series[i+lookback:i+lookback+horizon])
|
| 31 |
+
return np.array(X), np.array(y)
|
| 32 |
+
|
| 33 |
+
def train_lstm(series, lookback=30, epochs=20, lr=1e-3):
|
| 34 |
+
X, y = create_sequences(series, lookback=lookback, horizon=1)
|
| 35 |
+
X = torch.from_numpy(X).float().unsqueeze(-1) # (N, L, 1)
|
| 36 |
+
y = torch.from_numpy(y).float().squeeze(-1)
|
| 37 |
+
model = SimpleLSTM(input_size=1)
|
| 38 |
+
opt = torch.optim.Adam(model.parameters(), lr=lr)
|
| 39 |
+
loss_fn = nn.MSELoss()
|
| 40 |
+
model.train()
|
| 41 |
+
for ep in range(epochs):
|
| 42 |
+
pred = model(X)
|
| 43 |
+
loss = loss_fn(pred.squeeze(), y)
|
| 44 |
+
opt.zero_grad(); loss.backward(); opt.step()
|
| 45 |
+
return model
|
| 46 |
+
else:
|
| 47 |
+
def train_lstm(*args, **kwargs):
|
| 48 |
+
raise ImportError("PyTorch не установлен. Установите torch, чтобы использовать LSTM.")
|
src/streamlit_app.py
CHANGED
|
@@ -15,6 +15,29 @@ from statsmodels.tsa.seasonal import seasonal_decompose
|
|
| 15 |
from statsmodels.stats.outliers_influence import variance_inflation_factor
|
| 16 |
from statsmodels.tools import add_constant
|
| 17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
st.set_page_config(page_title="Анализ временных рядов", layout="wide", initial_sidebar_state="expanded")
|
| 19 |
MOSCOW = pytz.timezone("Europe/Moscow")
|
| 20 |
|
|
@@ -33,15 +56,39 @@ except ImportError as e:
|
|
| 33 |
LAB2_AVAILABLE = False
|
| 34 |
st.warning(f"Функции ЛР №2 недоступны: {e}")
|
| 35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
# Навигация между лабораторными работами
|
| 37 |
st.sidebar.title("🧪 Лабораторные работы")
|
| 38 |
lab_choice = st.sidebar.radio(
|
| 39 |
"Выберите лабораторную работу:",
|
| 40 |
-
["ЛР №1: Введение в анализ временных рядов",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
index=0
|
| 42 |
)
|
| 43 |
|
| 44 |
-
|
| 45 |
# ---------------- Utilities ----------------
|
| 46 |
def detect_date_column(df: pd.DataFrame) -> Optional[str]:
|
| 47 |
candidates = [c for c in df.columns if any(k in c.lower() for k in ("date", "time", "timestamp", "dt", "day"))]
|
|
@@ -1876,11 +1923,320 @@ def render_lab2():
|
|
| 1876 |
else:
|
| 1877 |
st.warning("⚠️ Сначала постройте модели в разделе 'Этап 6-7', чтобы увидеть результаты сравнения.")
|
| 1878 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1879 |
|
| 1880 |
# ---------------- Главный код: выбор лабораторной работы ----------------
|
| 1881 |
if lab_choice == "ЛР №1: Введение в анализ временных рядов":
|
| 1882 |
render_lab1()
|
| 1883 |
elif lab_choice == "ЛР №2: Прогнозирование временных рядов":
|
| 1884 |
render_lab2()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1885 |
else:
|
| 1886 |
st.info("Выберите лабораторную работу в боковой панели")
|
|
|
|
| 15 |
from statsmodels.stats.outliers_influence import variance_inflation_factor
|
| 16 |
from statsmodels.tools import add_constant
|
| 17 |
|
| 18 |
+
import sys
|
| 19 |
+
import os
|
| 20 |
+
|
| 21 |
+
# Добавляем папку с модулями (путь к файлу streamlit_app.py)
|
| 22 |
+
# Это гарантирует, что Python найдёт lab3_pipeline и lab3_functions в той же папке src
|
| 23 |
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
| 24 |
+
|
| 25 |
+
try:
|
| 26 |
+
import lab3_functions as lab3
|
| 27 |
+
from lab3_pipeline import run_pipeline
|
| 28 |
+
LAB3_AVAILABLE = True
|
| 29 |
+
except Exception as e:
|
| 30 |
+
LAB3_AVAILABLE = False
|
| 31 |
+
lab3 = None
|
| 32 |
+
_LAB3_IMPORT_ERROR = str(e)
|
| 33 |
+
# Для дебага выведем в консоль (и в Streamlit, если он загружен)
|
| 34 |
+
print("lab3 import failed:", _LAB3_IMPORT_ERROR)
|
| 35 |
+
try:
|
| 36 |
+
import streamlit as _st
|
| 37 |
+
_st.warning("lab3 import failed: " + _LAB3_IMPORT_ERROR)
|
| 38 |
+
except Exception:
|
| 39 |
+
pass
|
| 40 |
+
|
| 41 |
st.set_page_config(page_title="Анализ временных рядов", layout="wide", initial_sidebar_state="expanded")
|
| 42 |
MOSCOW = pytz.timezone("Europe/Moscow")
|
| 43 |
|
|
|
|
| 56 |
LAB2_AVAILABLE = False
|
| 57 |
st.warning(f"Функции ЛР №2 недоступны: {e}")
|
| 58 |
|
| 59 |
+
# после импорта lab2_functions
|
| 60 |
+
try:
|
| 61 |
+
import lab3_functions as lab3
|
| 62 |
+
LAB3_AVAILABLE = True
|
| 63 |
+
except Exception:
|
| 64 |
+
LAB3_AVAILABLE = False
|
| 65 |
+
|
| 66 |
+
try:
|
| 67 |
+
import lab4_functions as lab4
|
| 68 |
+
LAB4_AVAILABLE = True
|
| 69 |
+
except Exception:
|
| 70 |
+
LAB4_AVAILABLE = False
|
| 71 |
+
|
| 72 |
+
try:
|
| 73 |
+
import lab5_functions as lab5
|
| 74 |
+
LAB5_AVAILABLE = True
|
| 75 |
+
except Exception:
|
| 76 |
+
LAB5_AVAILABLE = False
|
| 77 |
+
|
| 78 |
+
|
| 79 |
# Навигация между лабораторными работами
|
| 80 |
st.sidebar.title("🧪 Лабораторные работы")
|
| 81 |
lab_choice = st.sidebar.radio(
|
| 82 |
"Выберите лабораторную работу:",
|
| 83 |
+
["ЛР №1: Введение в анализ временных рядов",
|
| 84 |
+
"ЛР №2: Прогнозирование временных рядов",
|
| 85 |
+
"ЛР №3: Классические модели",
|
| 86 |
+
"ЛР №4: ML для TS",
|
| 87 |
+
"ЛР №5: Deep Learning для TS"
|
| 88 |
+
],
|
| 89 |
index=0
|
| 90 |
)
|
| 91 |
|
|
|
|
| 92 |
# ---------------- Utilities ----------------
|
| 93 |
def detect_date_column(df: pd.DataFrame) -> Optional[str]:
|
| 94 |
candidates = [c for c in df.columns if any(k in c.lower() for k in ("date", "time", "timestamp", "dt", "day"))]
|
|
|
|
| 1923 |
else:
|
| 1924 |
st.warning("⚠️ Сначала постройте модели в разделе 'Этап 6-7', чтобы увидеть результаты сравнения.")
|
| 1925 |
|
| 1926 |
+
import streamlit.components.v1 as components
|
| 1927 |
+
import pandas as pd
|
| 1928 |
+
from pathlib import Path
|
| 1929 |
+
|
| 1930 |
+
def render_lab3():
|
| 1931 |
+
st.title("🧪 ЛР №3: Сравнительный анализ классических моделей")
|
| 1932 |
+
|
| 1933 |
+
if not LAB3_AVAILABLE:
|
| 1934 |
+
st.error("Модуль lab3_functions / lab3_pipeline недоступен. Добавьте файлы в папку src.")
|
| 1935 |
+
if '_LAB3_IMPORT_ERROR' in globals():
|
| 1936 |
+
st.write("Ошибка импорта:", _LAB3_IMPORT_ERROR)
|
| 1937 |
+
return
|
| 1938 |
+
|
| 1939 |
+
st.info("Загрузи/выбери датасет в ЛР1 и запусти preprocess — затем сюда.")
|
| 1940 |
+
if 'df_clean' not in st.session_state:
|
| 1941 |
+
st.info("Сначала выполните ЛР1: загрузите и предобработайте датасет.")
|
| 1942 |
+
return
|
| 1943 |
+
|
| 1944 |
+
df = st.session_state['df_clean'].copy()
|
| 1945 |
+
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist() if 'pd' in globals() else df.select_dtypes(include=['number']).columns.tolist()
|
| 1946 |
+
if not numeric_cols:
|
| 1947 |
+
st.error("Нет числовых колонок.")
|
| 1948 |
+
return
|
| 1949 |
+
|
| 1950 |
+
target = st.selectbox("Выберите target для ЛР3", numeric_cols)
|
| 1951 |
+
# Убедимся, что timestamp есть в датафрейме (если он в индексе — reset_index сделает колонку)
|
| 1952 |
+
if 'timestamp' not in df.columns:
|
| 1953 |
+
try:
|
| 1954 |
+
df_reset = df.reset_index()
|
| 1955 |
+
if 'timestamp' in df_reset.columns:
|
| 1956 |
+
df = df_reset
|
| 1957 |
+
else:
|
| 1958 |
+
st.error("Колонка 'timestamp' не найдена. Убедитесь, что в df_clean есть временная метка.")
|
| 1959 |
+
return
|
| 1960 |
+
except Exception:
|
| 1961 |
+
st.error("Не удалось найти колонку 'timestamp'.")
|
| 1962 |
+
return
|
| 1963 |
+
|
| 1964 |
+
series = df.set_index('timestamp')[target].dropna()
|
| 1965 |
+
st.write("Длина ряда:", len(series))
|
| 1966 |
+
|
| 1967 |
+
# ---- существующие экспандеры ARIMA/VAR оставляем без изменений ----
|
| 1968 |
+
# === ARIMA / auto_arima expander ===
|
| 1969 |
+
with st.expander("ARIMA / auto_arima (SARIMAX)"):
|
| 1970 |
+
import numpy as _np
|
| 1971 |
+
import pandas as _pd
|
| 1972 |
+
import matplotlib.pyplot as _plt
|
| 1973 |
+
|
| 1974 |
+
use_auto = st.checkbox("Использовать auto_arima (pmdarima)", value=False)
|
| 1975 |
+
col_freq = st.selectbox("Частота ряда (inference если None)", ["auto", "D", "W", "M"], index=0)
|
| 1976 |
+
|
| 1977 |
+
if use_auto:
|
| 1978 |
+
max_p = st.number_input("max_p (для auto_arima)", min_value=0, max_value=10, value=3, step=1)
|
| 1979 |
+
max_d = st.number_input("max_d", min_value=0, max_value=3, value=2, step=1)
|
| 1980 |
+
max_q = st.number_input("max_q", min_value=0, max_value=10, value=3, step=1)
|
| 1981 |
+
seasonal = st.checkbox("Ищем сезонность (seasonal)", value=False)
|
| 1982 |
+
seasonal_period = st.number_input("m (период сезонности, если seasonal=True)", min_value=0, max_value=366, value=7, step=1)
|
| 1983 |
+
if st.button("Запустить auto_arima"):
|
| 1984 |
+
try:
|
| 1985 |
+
with st.spinner("Подбираю модель auto_arima..."):
|
| 1986 |
+
model = lab3.fit_auto_arima(series, seasonal=seasonal, m=int(seasonal_period),
|
| 1987 |
+
start_p=0, start_q=0, max_p=int(max_p), max_q=int(max_q),
|
| 1988 |
+
max_d=int(max_d))
|
| 1989 |
+
st.success("auto_arima выполнен")
|
| 1990 |
+
# pmdarima object имеет summary или order/seasonal_order
|
| 1991 |
+
try:
|
| 1992 |
+
st.text(str(model.summary()))
|
| 1993 |
+
except Exception:
|
| 1994 |
+
st.write("Выбран порядок:", getattr(model, "order", None))
|
| 1995 |
+
st.write("seasonal_order:", getattr(model, "seasonal_order", None))
|
| 1996 |
+
st.session_state['_lab3_last_model'] = ("auto_arima", model)
|
| 1997 |
+
except Exception as e:
|
| 1998 |
+
st.error("Ошибка auto_arima: " + str(e))
|
| 1999 |
+
|
| 2000 |
+
else:
|
| 2001 |
+
# ручная SARIMAX
|
| 2002 |
+
st.write("Параметры SARIMAX (ручной режим)")
|
| 2003 |
+
p = st.number_input("p (AR)", min_value=0, max_value=10, value=1, step=1)
|
| 2004 |
+
d = st.number_input("d (diff)", min_value=0, max_value=3, value=0, step=1)
|
| 2005 |
+
q = st.number_input("q (MA)", min_value=0, max_value=10, value=0, step=1)
|
| 2006 |
+
sp = st.number_input("P (seasonal AR)", min_value=0, max_value=5, value=0, step=1)
|
| 2007 |
+
sd = st.number_input("D (seasonal diff)", min_value=0, max_value=2, value=0, step=1)
|
| 2008 |
+
sq = st.number_input("Q (seasonal MA)", min_value=0, max_value=5, value=0, step=1)
|
| 2009 |
+
s = st.number_input("s (seasonal period)", min_value=0, max_value=366, value=7, step=1)
|
| 2010 |
+
if st.button("Построить SARIMAX (ручной)"):
|
| 2011 |
+
try:
|
| 2012 |
+
with st.spinner("Обучаю SARIMAX..."):
|
| 2013 |
+
res = lab3.fit_sarimax(series, order=(int(p), int(d), int(q)),
|
| 2014 |
+
seasonal_order=(int(sp), int(sd), int(sq), int(s)))
|
| 2015 |
+
st.success("SARIMAX обучен")
|
| 2016 |
+
try:
|
| 2017 |
+
st.text(res.summary().as_text())
|
| 2018 |
+
except Exception:
|
| 2019 |
+
st.write("Модель успешно обучена. Объект результата:", type(res))
|
| 2020 |
+
st.session_state['_lab3_last_model'] = ("sarimax", res)
|
| 2021 |
+
except Exception as e:
|
| 2022 |
+
st.error("Ошибка SARIMAX: " + str(e))
|
| 2023 |
+
|
| 2024 |
+
# Forecast controls (общие)
|
| 2025 |
+
st.markdown("**Прогноз (forecast)**")
|
| 2026 |
+
fh = st.slider("Горизонт прогнозирования (h)", min_value=1, max_value=90, value=7)
|
| 2027 |
+
if st.button("Сделать прогноз (последние точки + future)"):
|
| 2028 |
+
if '_lab3_last_model' not in st.session_state:
|
| 2029 |
+
st.error("Сначала обучите модель (auto_arima или SARIMAX).")
|
| 2030 |
+
else:
|
| 2031 |
+
mtype, mobj = st.session_state['_lab3_last_model']
|
| 2032 |
+
try:
|
| 2033 |
+
if mtype == "auto_arima":
|
| 2034 |
+
# pmdarima.predict возвращает массив
|
| 2035 |
+
preds = mobj.predict(n_periods=fh)
|
| 2036 |
+
# создаём индекс для будущих дат
|
| 2037 |
+
if col_freq == "auto":
|
| 2038 |
+
freq = _pd.infer_freq(series.index) or "D"
|
| 2039 |
+
else:
|
| 2040 |
+
freq = col_freq
|
| 2041 |
+
last = series.index[-1]
|
| 2042 |
+
future_index = _pd.date_range(start=last + _pd.tseries.frequencies.to_offset(freq), periods=fh, freq=freq)
|
| 2043 |
+
pred_series = _pd.Series(preds, index=future_index, name=f"pred_auto_arima_h{fh}")
|
| 2044 |
+
st.line_chart(_pd.concat([series.tail(200), pred_series]))
|
| 2045 |
+
st.write(pred_series.to_frame("forecast"))
|
| 2046 |
+
else:
|
| 2047 |
+
# SARIMAX result
|
| 2048 |
+
mean, (low, high) = lab3.forecast_sarimax(mobj, steps=fh)
|
| 2049 |
+
if col_freq == "auto":
|
| 2050 |
+
freq = _pd.infer_freq(series.index) or "D"
|
| 2051 |
+
else:
|
| 2052 |
+
freq = col_freq
|
| 2053 |
+
last = series.index[-1]
|
| 2054 |
+
future_index = _pd.date_range(start=last + _pd.tseries.frequencies.to_offset(freq), periods=fh, freq=freq)
|
| 2055 |
+
pred_series = _pd.Series(mean, index=future_index)
|
| 2056 |
+
low_s = _pd.Series(low, index=future_index)
|
| 2057 |
+
high_s = _pd.Series(high, index=future_index)
|
| 2058 |
+
fig, ax = _plt.subplots(figsize=(10, 4))
|
| 2059 |
+
ax.plot(series.tail(200).index, series.tail(200).values, label="history")
|
| 2060 |
+
ax.plot(pred_series.index, pred_series.values, label="forecast")
|
| 2061 |
+
ax.fill_between(pred_series.index, low_s.values, high_s.values, alpha=0.25, label="CI")
|
| 2062 |
+
ax.legend()
|
| 2063 |
+
st.pyplot(fig)
|
| 2064 |
+
st.write(pred_series.to_frame("forecast"))
|
| 2065 |
+
except Exception as e:
|
| 2066 |
+
st.error("Ошибка при прогнозе: " + str(e))
|
| 2067 |
+
|
| 2068 |
+
# Residuals diagnostics
|
| 2069 |
+
if st.checkbox("Показать диагностику остатков (последняя обученная модель)"):
|
| 2070 |
+
if '_lab3_last_model' not in st.session_state:
|
| 2071 |
+
st.info("Нет обученной модели в сессии.")
|
| 2072 |
+
else:
|
| 2073 |
+
try:
|
| 2074 |
+
mtype, mobj = st.session_state['_lab3_last_model']
|
| 2075 |
+
if mtype == "sarimax":
|
| 2076 |
+
resid = mobj.resid.dropna()
|
| 2077 |
+
elif mtype == "auto_arima":
|
| 2078 |
+
# у pmdarima есть attribute resid_ или можно считать inplace prediction
|
| 2079 |
+
try:
|
| 2080 |
+
resid = _pd.Series(mobj.resid())
|
| 2081 |
+
except Exception:
|
| 2082 |
+
resid = None
|
| 2083 |
+
else:
|
| 2084 |
+
resid = None
|
| 2085 |
+
|
| 2086 |
+
if resid is None or len(resid) == 0:
|
| 2087 |
+
st.warning("Не удалось получить остатки для этой модели.")
|
| 2088 |
+
else:
|
| 2089 |
+
fig1, ax1 = _plt.subplots(1, 1, figsize=(8, 2.5))
|
| 2090 |
+
ax1.plot(resid)
|
| 2091 |
+
ax1.set_title("Остатки (time series)")
|
| 2092 |
+
st.pyplot(fig1)
|
| 2093 |
+
|
| 2094 |
+
fig2, ax2 = _plt.subplots(1, 1, figsize=(6, 3))
|
| 2095 |
+
ax2.hist(resid, bins=30)
|
| 2096 |
+
ax2.set_title("Гистограмма остатков")
|
| 2097 |
+
st.pyplot(fig2)
|
| 2098 |
+
|
| 2099 |
+
# Ljung-Box, если доступен
|
| 2100 |
+
try:
|
| 2101 |
+
from statsmodels.stats.diagnostic import acorr_ljungbox
|
| 2102 |
+
lb = acorr_ljungbox(resid, lags=[10], return_df=True)
|
| 2103 |
+
st.write("Ljung-Box (lag=10):")
|
| 2104 |
+
st.write(lb)
|
| 2105 |
+
except Exception:
|
| 2106 |
+
st.info("acorr_ljungbox недоступен в окружении.")
|
| 2107 |
+
except Exception as e:
|
| 2108 |
+
st.error("Ошибка диагностики: " + str(e))
|
| 2109 |
+
|
| 2110 |
+
# === VAR (multivariate) expander ===
|
| 2111 |
+
with st.expander("VAR (векторная авторегрессия) — multivariate"):
|
| 2112 |
+
import pandas as _pd
|
| 2113 |
+
import matplotlib.pyplot as _plt
|
| 2114 |
+
|
| 2115 |
+
st.write("Выберите колонки для VAR (минимум 2):")
|
| 2116 |
+
var_cols = st.multiselect("Колонки для VAR", options=numeric_cols, default=numeric_cols[:3])
|
| 2117 |
+
maxlags = st.number_input("maxlags (select_order)", min_value=1, max_value=20, value=5, step=1)
|
| 2118 |
+
if st.button("Построить VAR"):
|
| 2119 |
+
if len(var_cols) < 2:
|
| 2120 |
+
st.error("Нужно хотя бы 2 колонки для VAR.")
|
| 2121 |
+
else:
|
| 2122 |
+
try:
|
| 2123 |
+
df_var = df.set_index('timestamp')[var_cols].dropna()
|
| 2124 |
+
with st.spinner("Обучаю VAR..."):
|
| 2125 |
+
var_res = lab3.fit_var(df_var, maxlags=int(maxlags))
|
| 2126 |
+
st.success("VAR обучен, lag order = %s" % getattr(var_res, "k_ar", "unknown"))
|
| 2127 |
+
try:
|
| 2128 |
+
st.text(var_res.summary().as_text())
|
| 2129 |
+
except Exception:
|
| 2130 |
+
st.write("VAR results object:", type(var_res))
|
| 2131 |
+
st.session_state['_lab3_last_var'] = var_res
|
| 2132 |
+
except Exception as e:
|
| 2133 |
+
st.error("Ошибка VAR: " + str(e))
|
| 2134 |
+
|
| 2135 |
+
# Forecast for VAR
|
| 2136 |
+
st.markdown("**Прогноз VAR**")
|
| 2137 |
+
if st.button("Сделать VAR-прогноз (30 шагов)"):
|
| 2138 |
+
if '_lab3_last_var' not in st.session_state:
|
| 2139 |
+
st.error("Сначала обучите VAR.")
|
| 2140 |
+
else:
|
| 2141 |
+
try:
|
| 2142 |
+
var_res = st.session_state['_lab3_last_var']
|
| 2143 |
+
steps = st.number_input("h (шагов вперёд)", min_value=1, max_value=365, value=30, step=1)
|
| 2144 |
+
fut = lab3.forecast_var(var_res, steps=int(steps))
|
| 2145 |
+
st.write("Прогноз (DataFrame):")
|
| 2146 |
+
st.dataframe(fut)
|
| 2147 |
+
# Нарисуем прогноз по каждой переменной вместе с последними историческими точками
|
| 2148 |
+
df_var = df.set_index('timestamp')[var_cols].dropna()
|
| 2149 |
+
last_hist = df_var.tail(50)
|
| 2150 |
+
fig, ax = _plt.subplots(len(var_cols), 1, figsize=(10, 3*len(var_cols)), sharex=True)
|
| 2151 |
+
if len(var_cols) == 1:
|
| 2152 |
+
ax = [ax]
|
| 2153 |
+
for i, col in enumerate(var_cols):
|
| 2154 |
+
ax[i].plot(last_hist.index, last_hist[col].values, label=f"history_{col}")
|
| 2155 |
+
# построим future index
|
| 2156 |
+
freq = _pd.infer_freq(df_var.index) or "D"
|
| 2157 |
+
future_index = _pd.date_range(start=df_var.index[-1] + _pd.tseries.frequencies.to_offset(freq),
|
| 2158 |
+
periods=len(fut), freq=freq)
|
| 2159 |
+
ax[i].plot(future_index, fut[col].values, label=f"forecast_{col}")
|
| 2160 |
+
ax[i].legend()
|
| 2161 |
+
st.pyplot(fig)
|
| 2162 |
+
except Exception as e:
|
| 2163 |
+
st.error("Ошибка при VAR-прогнозе: " + str(e))
|
| 2164 |
+
|
| 2165 |
+
|
| 2166 |
+
# --- Новый блок: полный pipeline (run_pipeline) ---
|
| 2167 |
+
st.markdown("---")
|
| 2168 |
+
st.subheader("Запустить полный pipeline ЛР3 (генерация HTML-отчёта)")
|
| 2169 |
+
out_report = st.text_input("Путь для отчёта (HTML)", "./lab3_report.html")
|
| 2170 |
+
freq = st.selectbox("Частота ресемплинга", ['D','W','M'])
|
| 2171 |
+
|
| 2172 |
+
if st.button("Запустить полный pipeline и сформировать отчёт"):
|
| 2173 |
+
tmp = "./_lab3_input_tmp.csv"
|
| 2174 |
+
# сохраняем df с колонкой timestamp
|
| 2175 |
+
df.to_csv(tmp, index=False)
|
| 2176 |
+
st.info("Запускаю pipeline — это может занять время.")
|
| 2177 |
+
try:
|
| 2178 |
+
# run_pipeline ожидает путь к файлу
|
| 2179 |
+
run_pipeline(tmp, timestamp_col='timestamp', target_col=target, out_report=out_report, freq=freq)
|
| 2180 |
+
st.success("Готово — отчёт сохранён: " + out_report)
|
| 2181 |
+
if Path(out_report).exists():
|
| 2182 |
+
with open(out_report, 'r', encoding='utf-8') as f:
|
| 2183 |
+
html = f.read()
|
| 2184 |
+
components.html(html, height=800, scrolling=True)
|
| 2185 |
+
else:
|
| 2186 |
+
st.info("Отчёт создан, но файл не найден по указанному пути: " + out_report)
|
| 2187 |
+
except Exception as e:
|
| 2188 |
+
st.error("Ошибка при выполнении pipeline: " + str(e))
|
| 2189 |
+
|
| 2190 |
+
|
| 2191 |
+
def render_lab4():
|
| 2192 |
+
st.title("🧪 ЛР №4: ML-модели")
|
| 2193 |
+
if not LAB4_AVAILABLE:
|
| 2194 |
+
st.error("Модуль lab4_functions недоступен.")
|
| 2195 |
+
return
|
| 2196 |
+
if 'df_clean' not in st.session_state:
|
| 2197 |
+
st.info("Сначала выполните ЛР1: загрузите и предобработайте датасет.")
|
| 2198 |
+
return
|
| 2199 |
+
df = st.session_state['df_clean']
|
| 2200 |
+
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
|
| 2201 |
+
target = st.selectbox("Target", numeric_cols)
|
| 2202 |
+
if st.button("Сгенерировать простые лаги и обучить модели"):
|
| 2203 |
+
dfr = lab4.make_lag_features(df, target, lags=[1,7,30])
|
| 2204 |
+
X = dfr.drop(columns=['timestamp', target])
|
| 2205 |
+
y = dfr[target]
|
| 2206 |
+
models = lab4.train_baselines(X, y)
|
| 2207 |
+
st.write("Обученные модели:", list(models.keys()))
|
| 2208 |
+
for name, m in models.items():
|
| 2209 |
+
st.write(name, getattr(m, 'score', lambda X,y: None)(X, y) )
|
| 2210 |
+
|
| 2211 |
+
def render_lab5():
|
| 2212 |
+
st.title("🧪 ЛР №5: Deep Learning")
|
| 2213 |
+
if not LAB5_AVAILABLE:
|
| 2214 |
+
st.error("Модуль lab5_functions недоступен.")
|
| 2215 |
+
return
|
| 2216 |
+
if 'df_clean' not in st.session_state:
|
| 2217 |
+
st.info("Сначала выполните ЛР1.")
|
| 2218 |
+
return
|
| 2219 |
+
df = st.session_state['df_clean']
|
| 2220 |
+
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
|
| 2221 |
+
target = st.selectbox("Target для DL", numeric_cols)
|
| 2222 |
+
if st.button("Обучить простой LSTM (demo)"):
|
| 2223 |
+
s = df.set_index('timestamp')[target].dropna().values
|
| 2224 |
+
try:
|
| 2225 |
+
model = lab5.train_lstm(s, lookback=30, epochs=5)
|
| 2226 |
+
st.success("Модель обучена (demo).")
|
| 2227 |
+
except Exception as e:
|
| 2228 |
+
st.error(str(e))
|
| 2229 |
|
| 2230 |
# ---------------- Главный код: выбор лабораторной работы ----------------
|
| 2231 |
if lab_choice == "ЛР №1: Введение в анализ временных рядов":
|
| 2232 |
render_lab1()
|
| 2233 |
elif lab_choice == "ЛР №2: Прогнозирование временных рядов":
|
| 2234 |
render_lab2()
|
| 2235 |
+
elif lab_choice == "ЛР №3: Классические модели":
|
| 2236 |
+
render_lab3()
|
| 2237 |
+
elif lab_choice == "ЛР №4: ML для TS":
|
| 2238 |
+
render_lab4()
|
| 2239 |
+
elif lab_choice == "ЛР №5: Deep Learning для TS":
|
| 2240 |
+
render_lab5()
|
| 2241 |
else:
|
| 2242 |
st.info("Выберите лабораторную работу в боковой панели")
|
src/streamlit_lab3.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
streamlit_lab3.py
|
| 3 |
+
Упрощённый Streamlit-интерфейс для ЛР №3.
|
| 4 |
+
Позволяет загрузить CSV/Parquet, настроить параметры и запустить pipeline (lab3_pipeline.run_pipeline).
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import streamlit as st
|
| 8 |
+
import os
|
| 9 |
+
import pandas as pd
|
| 10 |
+
import tempfile
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
|
| 13 |
+
# импортируем наш pipeline (если он в PATH)
|
| 14 |
+
try:
|
| 15 |
+
from lab3_pipeline import run_pipeline
|
| 16 |
+
PIPELINE_AVAILABLE = True
|
| 17 |
+
except Exception as e:
|
| 18 |
+
PIPELINE_AVAILABLE = False
|
| 19 |
+
st = None
|
| 20 |
+
|
| 21 |
+
def main():
|
| 22 |
+
st.title('ЛР №3 — Временные ряды (pipeline)')
|
| 23 |
+
uploaded = st.file_uploader("Загрузите CSV/Parquet с колонкой timestamp и target", type=['csv','parquet'])
|
| 24 |
+
if uploaded is None:
|
| 25 |
+
st.info("Загрузите файл, или введите путь к локальному файлу на сервере.")
|
| 26 |
+
else:
|
| 27 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=Path(uploaded.name).suffix) as tmp:
|
| 28 |
+
tmp.write(uploaded.getbuffer())
|
| 29 |
+
tmp_path = tmp.name
|
| 30 |
+
st.write("Файл загружен:", tmp_path)
|
| 31 |
+
timestamp = st.text_input("Имя колонки с временной меткой", "timestamp")
|
| 32 |
+
target = st.text_input("Имя колонки с целевой переменной", "target")
|
| 33 |
+
freq = st.selectbox("Частота ресемплинга", ['D','W','M'])
|
| 34 |
+
outpath = './lab3_report.html'
|
| 35 |
+
if st.button("Запустить ЛР3"):
|
| 36 |
+
st.info("Запуск pipeline — может занять время. Выходной файл: " + outpath)
|
| 37 |
+
try:
|
| 38 |
+
run_pipeline(tmp_path, timestamp, target, out_report=outpath, freq=freq)
|
| 39 |
+
with open(outpath, 'r', encoding='utf-8') as f:
|
| 40 |
+
html = f.read()
|
| 41 |
+
st.markdown("### Отчёт")
|
| 42 |
+
st.components.v1.html(html, height=800, scrolling=True)
|
| 43 |
+
except Exception as e:
|
| 44 |
+
st.error("Ошибка при выполнении pipeline: " + str(e))
|
| 45 |
+
|
| 46 |
+
if __name__ == '__main__':
|
| 47 |
+
if PIPELINE_AVAILABLE:
|
| 48 |
+
main()
|
| 49 |
+
else:
|
| 50 |
+
print("lab3_pipeline недоступен. Положите lab3_pipeline.py в PYTHONPATH или /mnt/data")
|