Kolesnikov Dmitry commited on
Commit
b34a74f
·
1 Parent(s): eaf6e74

feat: Sarima и VAR для третей лабораторки

Browse files
_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
- seaborn
 
 
 
 
 
 
 
 
 
 
 
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: Введение в анализ временных рядов", "ЛР №2: Прогнозирование временных рядов"],
 
 
 
 
 
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")