moex-ruby 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eae95925bc7eac4a2000d9b1cb42470a92331b3a425ecec753127c0791bd65b1
4
- data.tar.gz: 07b79afe91e8a75c98b62f2e26dfb0af6ff2ee2becbbde98ee79753751320b78
3
+ metadata.gz: 96304edeae200088f924df138499e2cf6ff51b9e0b7811d776efcbd7bc6bcf40
4
+ data.tar.gz: 002e7b82831276a6f06ac926ca6520a41f80c45a9a13fc3feef807647c755bcd
5
5
  SHA512:
6
- metadata.gz: '09f2529e1d66efcdb026eaabc7ad96b363fb5e313364773e57e42f3c0cfa28804ee6b08d7222e41f8e2327d9f35948caa4f82f806b3fc305fb0c5993c2d5dbc1'
7
- data.tar.gz: 9e0f1b8fa84e21e08759caf062fc8de266b9b3eee98ebcfdb29da175677aa3c91ab50c8de1ad207427fd31c8031568e044198d9215da383844128a51567a9820
6
+ metadata.gz: 4755e204724bac25b72338f256719ba8fd7f2d2ec4e442fed9f3e2d271c05414d8d9a2130e62b30f6499460fe500ca645ea3300c82db3f042869173dcca0cad6
7
+ data.tar.gz: 4aedf5b07511cf4fbff743ae3a0eb3a1855e8f3fcb5ffd53bbb80d8cd80c81be2381df8ce11b9231353692f6cad31100d2c238431cc31749199543fd4f6aa0e4
data/.gitignore CHANGED
@@ -55,4 +55,8 @@ build-iPhoneSimulator/
55
55
  # Used by RuboCop. Remote config files pulled in from inherit_from directive.
56
56
  # .rubocop-https?--*
57
57
  /.idea/
58
- /.supercode/
58
+ /.supercode/
59
+ test_moex.rb
60
+ TESTING.md
61
+ /examples/
62
+ /.cursor/
data/.rspec_status CHANGED
@@ -1,4 +1,179 @@
1
- example_id | status | run_time |
2
- ----------------------------- | ------ | --------------- |
3
- ./spec/moex_ruby_spec.rb[1:1] | passed | 0.00059 seconds |
4
- ./spec/moex_ruby_spec.rb[1:2] | passed | 0.00004 seconds |
1
+ example_id | status | run_time |
2
+ ---------------------------------------------------- | ------ | --------------- |
3
+ ./spec/moex_ruby/client/engines_spec.rb[1:1:1] | passed | 0.01312 seconds |
4
+ ./spec/moex_ruby/client/engines_spec.rb[1:2:1] | passed | 0.00416 seconds |
5
+ ./spec/moex_ruby/client/engines_spec.rb[1:3:1] | passed | 0.00381 seconds |
6
+ ./spec/moex_ruby/client/engines_spec.rb[1:4:1] | passed | 0.00392 seconds |
7
+ ./spec/moex_ruby/client/engines_spec.rb[1:5:1] | passed | 0.00396 seconds |
8
+ ./spec/moex_ruby/client/engines_spec.rb[1:6:1] | passed | 0.00478 seconds |
9
+ ./spec/moex_ruby/client/engines_spec.rb[1:7:1] | passed | 0.00825 seconds |
10
+ ./spec/moex_ruby/client/engines_spec.rb[1:8:1] | passed | 0.00606 seconds |
11
+ ./spec/moex_ruby/client/engines_spec.rb[1:9:1] | passed | 0.00424 seconds |
12
+ ./spec/moex_ruby/client/engines_spec.rb[1:10:1] | passed | 0.00433 seconds |
13
+ ./spec/moex_ruby/client/history_spec.rb[1:1:1] | passed | 0.00428 seconds |
14
+ ./spec/moex_ruby/client/history_spec.rb[1:1:2] | passed | 0.00466 seconds |
15
+ ./spec/moex_ruby/client/history_spec.rb[1:2:1] | passed | 0.004 seconds |
16
+ ./spec/moex_ruby/client/history_spec.rb[1:2:2] | passed | 0.00423 seconds |
17
+ ./spec/moex_ruby/client/history_spec.rb[1:3:1] | passed | 0.00387 seconds |
18
+ ./spec/moex_ruby/client/history_spec.rb[1:4:1] | passed | 0.00458 seconds |
19
+ ./spec/moex_ruby/client/history_spec.rb[1:5:1] | passed | 0.00426 seconds |
20
+ ./spec/moex_ruby/client/history_spec.rb[1:6:1] | passed | 0.0046 seconds |
21
+ ./spec/moex_ruby/client/history_spec.rb[1:7:1] | passed | 0.00486 seconds |
22
+ ./spec/moex_ruby/client/markets_spec.rb[1:1:1] | passed | 0.0042 seconds |
23
+ ./spec/moex_ruby/client/markets_spec.rb[1:1:2] | passed | 0.00428 seconds |
24
+ ./spec/moex_ruby/client/markets_spec.rb[1:2:1] | passed | 0.0041 seconds |
25
+ ./spec/moex_ruby/client/markets_spec.rb[1:3:1] | passed | 0.00415 seconds |
26
+ ./spec/moex_ruby/client/markets_spec.rb[1:4:1] | passed | 0.00412 seconds |
27
+ ./spec/moex_ruby/client/markets_spec.rb[1:4:2] | passed | 0.00437 seconds |
28
+ ./spec/moex_ruby/client/markets_spec.rb[1:5:1] | passed | 0.00406 seconds |
29
+ ./spec/moex_ruby/client/markets_spec.rb[1:6:1] | passed | 0.00399 seconds |
30
+ ./spec/moex_ruby/client/markets_spec.rb[1:7:1] | passed | 0.00401 seconds |
31
+ ./spec/moex_ruby/client/markets_spec.rb[1:7:2] | passed | 0.0044 seconds |
32
+ ./spec/moex_ruby/client/markets_spec.rb[1:8:1] | passed | 0.00417 seconds |
33
+ ./spec/moex_ruby/client/markets_spec.rb[1:9:1] | passed | 0.00527 seconds |
34
+ ./spec/moex_ruby/client/markets_spec.rb[1:9:2] | passed | 0.00449 seconds |
35
+ ./spec/moex_ruby/client/markets_spec.rb[1:10:1] | passed | 0.00445 seconds |
36
+ ./spec/moex_ruby/client/securities_spec.rb[1:1:1] | passed | 0.00411 seconds |
37
+ ./spec/moex_ruby/client/securities_spec.rb[1:1:2] | passed | 0.00424 seconds |
38
+ ./spec/moex_ruby/client/securities_spec.rb[1:2:1] | passed | 0.00406 seconds |
39
+ ./spec/moex_ruby/client/securities_spec.rb[1:2:2] | passed | 0.00428 seconds |
40
+ ./spec/moex_ruby/client/securities_spec.rb[1:3:1] | passed | 0.00419 seconds |
41
+ ./spec/moex_ruby/client/securities_spec.rb[1:3:2] | passed | 0.00429 seconds |
42
+ ./spec/moex_ruby/client/securities_spec.rb[1:4:1] | passed | 0.0041 seconds |
43
+ ./spec/moex_ruby/client/securities_spec.rb[1:5:1] | passed | 0.00413 seconds |
44
+ ./spec/moex_ruby/client/securities_spec.rb[1:6:1] | passed | 0.00518 seconds |
45
+ ./spec/moex_ruby/client_spec.rb[1:1:1] | passed | 0.00012 seconds |
46
+ ./spec/moex_ruby/client_spec.rb[1:1:2] | passed | 0.00011 seconds |
47
+ ./spec/moex_ruby/client_spec.rb[1:1:3] | passed | 0.00056 seconds |
48
+ ./spec/moex_ruby/client_spec.rb[1:1:4] | passed | 0.0001 seconds |
49
+ ./spec/moex_ruby/client_spec.rb[1:1:5] | passed | 0.00011 seconds |
50
+ ./spec/moex_ruby/client_spec.rb[1:1:6] | passed | 0.00009 seconds |
51
+ ./spec/moex_ruby/client_spec.rb[1:1:7] | passed | 0.0001 seconds |
52
+ ./spec/moex_ruby/client_spec.rb[1:1:8] | passed | 0.00009 seconds |
53
+ ./spec/moex_ruby/client_spec.rb[1:2:1] | passed | 0.0046 seconds |
54
+ ./spec/moex_ruby/client_spec.rb[1:2:2] | passed | 0.00417 seconds |
55
+ ./spec/moex_ruby/client_spec.rb[1:2:3] | passed | 0.0044 seconds |
56
+ ./spec/moex_ruby/client_spec.rb[1:2:4] | passed | 0.00555 seconds |
57
+ ./spec/moex_ruby/client_spec.rb[1:2:5] | passed | 0.00408 seconds |
58
+ ./spec/moex_ruby/client_spec.rb[1:3:1] | passed | 0.00559 seconds |
59
+ ./spec/moex_ruby/client_spec.rb[1:3:2] | passed | 0.00509 seconds |
60
+ ./spec/moex_ruby/client_spec.rb[1:3:3] | passed | 0.00517 seconds |
61
+ ./spec/moex_ruby/client_spec.rb[1:4:1] | passed | 0.00619 seconds |
62
+ ./spec/moex_ruby/client_spec.rb[1:4:2] | passed | 0.00452 seconds |
63
+ ./spec/moex_ruby/client_spec.rb[1:4:3] | passed | 0.00494 seconds |
64
+ ./spec/moex_ruby/client_spec.rb[1:4:4:1] | passed | 0.00919 seconds |
65
+ ./spec/moex_ruby/client_spec.rb[1:4:4:2] | passed | 0.0061 seconds |
66
+ ./spec/moex_ruby/client_spec.rb[1:4:4:3] | passed | 0.0058 seconds |
67
+ ./spec/moex_ruby/configuration_spec.rb[1:1:1] | passed | 0.00004 seconds |
68
+ ./spec/moex_ruby/configuration_spec.rb[1:2:1] | passed | 0.00004 seconds |
69
+ ./spec/moex_ruby/configuration_spec.rb[1:2:2] | passed | 0.00003 seconds |
70
+ ./spec/moex_ruby/configuration_spec.rb[1:2:3] | passed | 0.00003 seconds |
71
+ ./spec/moex_ruby/configuration_spec.rb[1:3:1] | passed | 0.00128 seconds |
72
+ ./spec/moex_ruby/configuration_spec.rb[1:3:2] | passed | 0.00261 seconds |
73
+ ./spec/moex_ruby/configuration_spec.rb[1:4:1] | passed | 0.00006 seconds |
74
+ ./spec/moex_ruby/configuration_spec.rb[1:4:2] | passed | 0.00004 seconds |
75
+ ./spec/moex_ruby/configuration_spec.rb[1:5:1] | passed | 0.00004 seconds |
76
+ ./spec/moex_ruby/configuration_spec.rb[1:5:2] | passed | 0.00003 seconds |
77
+ ./spec/moex_ruby/configuration_spec.rb[1:6:1] | passed | 0.00006 seconds |
78
+ ./spec/moex_ruby/configuration_spec.rb[1:6:2] | passed | 0.00004 seconds |
79
+ ./spec/moex_ruby/configuration_spec.rb[1:7:1] | passed | 0.00003 seconds |
80
+ ./spec/moex_ruby/configuration_spec.rb[1:8:1] | passed | 0.00003 seconds |
81
+ ./spec/moex_ruby/configuration_spec.rb[1:8:2] | passed | 0.00003 seconds |
82
+ ./spec/moex_ruby/configuration_spec.rb[1:9:1] | passed | 0.00003 seconds |
83
+ ./spec/moex_ruby/configuration_spec.rb[1:9:2] | passed | 0.00004 seconds |
84
+ ./spec/moex_ruby/configuration_spec.rb[1:9:3] | passed | 0.00003 seconds |
85
+ ./spec/moex_ruby/configuration_spec.rb[1:10:1] | passed | 0.00982 seconds |
86
+ ./spec/moex_ruby/configuration_spec.rb[1:10:2] | passed | 0.00016 seconds |
87
+ ./spec/moex_ruby/configuration_spec.rb[1:10:3] | passed | 0.0001 seconds |
88
+ ./spec/moex_ruby/configuration_spec.rb[1:10:4] | passed | 0.00005 seconds |
89
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:1] | passed | 0.00013 seconds |
90
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:2] | passed | 0.00011 seconds |
91
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:3] | passed | 0.0001 seconds |
92
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:4] | passed | 0.00011 seconds |
93
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:5] | passed | 0.0001 seconds |
94
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:6] | passed | 0.00009 seconds |
95
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:7] | passed | 0.00011 seconds |
96
+ ./spec/moex_ruby/connection_builder_spec.rb[1:1:8] | passed | 0.0001 seconds |
97
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:1:1] | passed | 0.00004 seconds |
98
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:1:2] | passed | 0.00204 seconds |
99
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:1:3] | passed | 0.00005 seconds |
100
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:2:1] | passed | 0.00004 seconds |
101
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:3:1] | passed | 0.00005 seconds |
102
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:4:1] | passed | 0.00005 seconds |
103
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:5:1] | passed | 0.00038 seconds |
104
+ ./spec/moex_ruby/data_transformer_spec.rb[1:1:5:2] | passed | 0.00495 seconds |
105
+ ./spec/moex_ruby/error_handler_spec.rb[1:1:1:1] | passed | 0.00007 seconds |
106
+ ./spec/moex_ruby/error_handler_spec.rb[1:1:2:1] | passed | 0.00004 seconds |
107
+ ./spec/moex_ruby/error_handler_spec.rb[1:1:3:1] | passed | 0.00022 seconds |
108
+ ./spec/moex_ruby/error_handler_spec.rb[1:1:4:1] | passed | 0.00018 seconds |
109
+ ./spec/moex_ruby/errors_spec.rb[1:1:1] | passed | 0.00004 seconds |
110
+ ./spec/moex_ruby/errors_spec.rb[1:1:2] | passed | 0.00003 seconds |
111
+ ./spec/moex_ruby/errors_spec.rb[1:1:3] | passed | 0.00003 seconds |
112
+ ./spec/moex_ruby/errors_spec.rb[1:1:4] | passed | 0.00003 seconds |
113
+ ./spec/moex_ruby/errors_spec.rb[1:1:5] | passed | 0.00003 seconds |
114
+ ./spec/moex_ruby/errors_spec.rb[1:1:6] | passed | 0.00003 seconds |
115
+ ./spec/moex_ruby/errors_spec.rb[1:1:7] | passed | 0.00003 seconds |
116
+ ./spec/moex_ruby/errors_spec.rb[1:1:8] | passed | 0.00003 seconds |
117
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:1:1] | passed | 0.00018 seconds |
118
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:1:2] | passed | 0.00013 seconds |
119
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:1:3] | passed | 0.00044 seconds |
120
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:1:4] | passed | 0.00012 seconds |
121
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:1] | passed | 0.00005 seconds |
122
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:2] | passed | 0.00004 seconds |
123
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:3] | passed | 0.00004 seconds |
124
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:4] | passed | 0.00003 seconds |
125
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:5:1] | passed | 0.00016 seconds |
126
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:5:2] | passed | 0.00014 seconds |
127
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:5:3] | passed | 0.00014 seconds |
128
+ ./spec/moex_ruby/faraday_connection_spec.rb[1:2:5:4] | passed | 0.00013 seconds |
129
+ ./spec/moex_ruby/lazy_result_spec.rb[1:1:1] | passed | 0.00005 seconds |
130
+ ./spec/moex_ruby/lazy_result_spec.rb[1:1:2] | passed | 0.00004 seconds |
131
+ ./spec/moex_ruby/lazy_result_spec.rb[1:2:1] | passed | 0.00004 seconds |
132
+ ./spec/moex_ruby/lazy_result_spec.rb[1:2:2] | passed | 0.00004 seconds |
133
+ ./spec/moex_ruby/lazy_result_spec.rb[1:3:1] | passed | 0.00004 seconds |
134
+ ./spec/moex_ruby/lazy_result_spec.rb[1:4:1] | passed | 0.00003 seconds |
135
+ ./spec/moex_ruby/lazy_result_spec.rb[1:4:2] | passed | 0.00004 seconds |
136
+ ./spec/moex_ruby/lazy_result_spec.rb[1:5:1] | passed | 0.00004 seconds |
137
+ ./spec/moex_ruby/lazy_result_spec.rb[1:6:1] | passed | 0.00004 seconds |
138
+ ./spec/moex_ruby/lazy_result_spec.rb[1:6:2] | passed | 0.00003 seconds |
139
+ ./spec/moex_ruby/lazy_result_spec.rb[1:7:1] | passed | 0.00004 seconds |
140
+ ./spec/moex_ruby/lazy_result_spec.rb[1:8:1] | passed | 0.00004 seconds |
141
+ ./spec/moex_ruby/lazy_result_spec.rb[1:8:2] | passed | 0.00004 seconds |
142
+ ./spec/moex_ruby/lazy_result_spec.rb[1:9:1] | passed | 0.00004 seconds |
143
+ ./spec/moex_ruby/lazy_result_spec.rb[1:9:2] | passed | 0.00003 seconds |
144
+ ./spec/moex_ruby/lazy_result_spec.rb[1:9:3] | passed | 0.00004 seconds |
145
+ ./spec/moex_ruby/lazy_result_spec.rb[1:9:4] | passed | 0.00004 seconds |
146
+ ./spec/moex_ruby/lazy_result_spec.rb[1:10:1] | passed | 0.00004 seconds |
147
+ ./spec/moex_ruby/lazy_result_spec.rb[1:10:2] | passed | 0.00004 seconds |
148
+ ./spec/moex_ruby/lazy_result_spec.rb[1:11:1] | passed | 0.00004 seconds |
149
+ ./spec/moex_ruby/lazy_result_spec.rb[1:11:2] | passed | 0.00004 seconds |
150
+ ./spec/moex_ruby/lazy_result_spec.rb[1:11:3] | passed | 0.00003 seconds |
151
+ ./spec/moex_ruby/lazy_result_spec.rb[1:11:4] | passed | 0.00012 seconds |
152
+ ./spec/moex_ruby/lazy_result_spec.rb[1:12:1] | passed | 0.00004 seconds |
153
+ ./spec/moex_ruby/lazy_result_spec.rb[1:12:2] | passed | 0.00004 seconds |
154
+ ./spec/moex_ruby/lazy_result_spec.rb[1:12:3] | passed | 0.00005 seconds |
155
+ ./spec/moex_ruby/lazy_result_spec.rb[1:12:4] | passed | 0.00005 seconds |
156
+ ./spec/moex_ruby/lazy_result_spec.rb[1:13:1] | passed | 0.00004 seconds |
157
+ ./spec/moex_ruby/lazy_result_spec.rb[1:13:2] | passed | 0.00004 seconds |
158
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:1] | passed | 0.00003 seconds |
159
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:2] | passed | 0.00003 seconds |
160
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:3] | passed | 0.00003 seconds |
161
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:4] | passed | 0.00008 seconds |
162
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:5] | passed | 0.00003 seconds |
163
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:6] | passed | 0.00003 seconds |
164
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:1:7] | passed | 0.00003 seconds |
165
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:1] | passed | 0.00003 seconds |
166
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:2] | passed | 0.00003 seconds |
167
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:3] | passed | 0.00003 seconds |
168
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:4] | passed | 0.00003 seconds |
169
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:5] | passed | 0.00003 seconds |
170
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:6] | passed | 0.00003 seconds |
171
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:7] | passed | 0.00004 seconds |
172
+ ./spec/moex_ruby/pagination_helper_spec.rb[1:2:8] | passed | 0.00003 seconds |
173
+ ./spec/moex_ruby/response_spec.rb[1:1:1] | passed | 0.00003 seconds |
174
+ ./spec/moex_ruby/response_spec.rb[1:1:2] | passed | 0.00003 seconds |
175
+ ./spec/moex_ruby/response_spec.rb[1:1:3] | passed | 0.00005 seconds |
176
+ ./spec/moex_ruby/response_spec.rb[1:1:4] | passed | 0.00004 seconds |
177
+ ./spec/moex_ruby/response_spec.rb[1:1:5] | passed | 0.00003 seconds |
178
+ ./spec/moex_ruby_spec.rb[1:1] | passed | 0.00004 seconds |
179
+ ./spec/moex_ruby_spec.rb[1:2] | passed | 0.00003 seconds |
data/Gemfile CHANGED
@@ -11,4 +11,5 @@ group :development, :test do
11
11
  gem 'rubocop', '~> 1.0'
12
12
  gem 'rubocop-rspec', '~> 2.0'
13
13
  gem 'simplecov', '~> 0.21'
14
+ gem 'webmock', '~> 3.0'
14
15
  end
data/Gemfile.lock CHANGED
@@ -1,26 +1,45 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- moex-ruby (0.0.1)
4
+ moex-ruby (0.0.2)
5
+ faraday (~> 2.0)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
10
+ addressable (2.8.7)
11
+ public_suffix (>= 2.0.2, < 7.0)
9
12
  ast (2.4.3)
13
+ bigdecimal (3.3.1)
14
+ crack (1.0.0)
15
+ bigdecimal
16
+ rexml
10
17
  diff-lcs (1.6.2)
11
18
  docile (1.4.1)
19
+ faraday (2.14.0)
20
+ faraday-net_http (>= 2.0, < 3.5)
21
+ json
22
+ logger
23
+ faraday-net_http (3.4.1)
24
+ net-http (>= 0.5.0)
25
+ hashdiff (1.2.1)
12
26
  json (2.15.1)
13
27
  language_server-protocol (3.17.0.5)
14
28
  lint_roller (1.1.0)
29
+ logger (1.7.0)
30
+ net-http (0.6.0)
31
+ uri
15
32
  parallel (1.27.0)
16
33
  parser (3.3.9.0)
17
34
  ast (~> 2.4.1)
18
35
  racc
19
36
  prism (1.6.0)
37
+ public_suffix (6.0.2)
20
38
  racc (1.8.1)
21
39
  rainbow (3.1.1)
22
40
  rake (13.3.0)
23
41
  regexp_parser (2.11.3)
42
+ rexml (3.4.4)
24
43
  rspec (3.13.2)
25
44
  rspec-core (~> 3.13.0)
26
45
  rspec-expectations (~> 3.13.0)
@@ -71,6 +90,11 @@ GEM
71
90
  unicode-display_width (3.2.0)
72
91
  unicode-emoji (~> 4.1)
73
92
  unicode-emoji (4.1.0)
93
+ uri (1.0.4)
94
+ webmock (3.25.1)
95
+ addressable (>= 2.8.0)
96
+ crack (>= 0.3.2)
97
+ hashdiff (>= 0.4.0, < 2.0.0)
74
98
 
75
99
  PLATFORMS
76
100
  arm64-darwin-24
@@ -83,6 +107,7 @@ DEPENDENCIES
83
107
  rubocop (~> 1.0)
84
108
  rubocop-rspec (~> 2.0)
85
109
  simplecov (~> 0.21)
110
+ webmock (~> 3.0)
86
111
 
87
112
  BUNDLED WITH
88
113
  2.7.2
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # moex-ruby
2
+ [![Gem Version](https://badge.fury.io/rb/moex-ruby.svg)](https://badge.fury.io/rb/moex-ruby)
2
3
 
3
4
  Ruby gem для работы с MOEX ISS API - интерфейсом информационной системы Московской Биржи.
4
5
 
@@ -6,8 +7,233 @@ Ruby gem для работы с MOEX ISS API - интерфейсом инфор
6
7
 
7
8
  Этот гем предоставляет удобный интерфейс для получения данных о торгах, инструментах, котировках и других аспектах Московской Биржи через официальное API ISS (Information & Statistical Server).
8
9
 
10
+ ## Установка
11
+
12
+ ```ruby
13
+ gem 'moex-ruby'
14
+ ```
15
+
16
+ или через Bundler:
17
+
18
+ ```bash
19
+ bundle add moex-ruby
20
+ ```
21
+
22
+ ## Быстрый старт
23
+
24
+ ```ruby
25
+ require 'moex_ruby'
26
+
27
+ # Базовое использование
28
+ client = MoexRuby::Client.new
29
+
30
+ # Получение данных о бумаге через модульный API
31
+ security = client.security('SBER')
32
+ puts security.inspect
33
+
34
+ # Поиск ценных бумаг
35
+ results = client.search_securities('Газпром')
36
+
37
+ # Исторические данные
38
+ history = client.security_history('SBER', from: '2024-01-01', till: '2024-01-31')
39
+
40
+ # Свечи (OHLC)
41
+ candles = client.candles('SBER', from: '2024-01-01', interval: 24)
42
+
43
+ # Автопагинация - получить ВСЕ результаты автоматически
44
+ client = MoexRuby::Client.new(auto_paginate: true)
45
+ all_securities = client.securities # Получит все страницы автоматически!
46
+ puts "Получено #{all_securities.count} бумаг"
47
+
48
+ # Ручная пагинация через все страницы
49
+ client.paginate_candles('SBER', from: '2024-01-01', interval: 24) do |page|
50
+ page.each { |candle| puts candle }
51
+ end
52
+
53
+ # Низкоуровневый доступ (по-прежнему доступен)
54
+ raw_data = client.get('/iss/securities/SBER')
55
+ ```
56
+
57
+ ## Конфигурация
58
+
59
+ ### Базовая конфигурация
60
+
61
+ ```ruby
62
+ # С таймаутом
63
+ client = MoexRuby::Client.new(timeout: 60)
64
+
65
+ # С автопагинацией (получать все страницы автоматически)
66
+ client = MoexRuby::Client.new(auto_paginate: true)
67
+
68
+ # С блоком конфигурации
69
+ client = MoexRuby::Client.new do |config|
70
+ config.timeout = 60
71
+ config.base_url = 'https://iss.moex.com'
72
+ config.auto_paginate = true
73
+ end
74
+ ```
75
+
76
+ ### Продвинутая конфигурация
77
+
78
+ ```ruby
79
+ client = MoexRuby::Client.new do |config|
80
+ # Добавление middleware
81
+ config.response :logger, nil, { bodies: true }
82
+ config.response :raise_error
83
+ config.request :url_encoded
84
+
85
+ # Выбор адаптера
86
+ config.adapter :net_http
87
+
88
+ # Автопагинация
89
+ config.auto_paginate = true
90
+ end
91
+ ```
92
+ ## Модульная архитектура
93
+
94
+ Гем использует модульную архитектуру, разделяя функциональность на логические группы:
95
+
96
+ ### Securities - Работа с ценными бумагами
97
+
98
+ ```ruby
99
+ # Информация о бумаге
100
+ client.security('SBER')
101
+
102
+ # Поиск
103
+ client.search_securities('Газпром', limit: 10)
104
+
105
+ # Список всех бумаг
106
+ client.securities(is_trading: 1)
107
+
108
+ # Индексы
109
+ client.indices
110
+ client.index('IMOEX')
111
+ ```
112
+
113
+ ### History - Исторические данные
114
+
115
+ ```ruby
116
+ # История торгов
117
+ client.security_history('SBER', from: '2024-01-01', till: '2024-01-31')
118
+
119
+ # Свечи (OHLC)
120
+ client.candles('SBER', from: '2024-01-01', interval: 24)
121
+
122
+ # Облигации
123
+ client.bond_history('RU000A0JXQ12', from: '2024-01-01')
124
+
125
+ # Валюта
126
+ client.currency_history('USD000UTSTOM', from: '2024-01-01')
127
+
128
+ # Пагинация
129
+ client.paginate_history('SBER', from: '2024-01-01') do |page|
130
+ page.each { |row| puts row }
131
+ end
132
+
133
+ client.paginate_candles('SBER', from: '2024-01-01', interval: 24) do |page|
134
+ page.each { |candle| puts candle }
135
+ end
136
+ ```
137
+
138
+ ### Engines - Торговые системы
139
+
140
+ ```ruby
141
+ # Список торговых систем
142
+ client.engines
143
+
144
+ # Рынки
145
+ client.markets('stock')
146
+
147
+ # Режимы торгов
148
+ client.boards('stock', 'shares')
149
+
150
+ # Бумаги на режиме
151
+ client.board_securities('stock', 'shares', 'TQBR')
152
+
153
+ # Котировки
154
+ client.board_security('stock', 'shares', 'TQBR', 'SBER')
155
+
156
+ # Алиасы
157
+ client.stock_shares # Акции на основном режиме
158
+ client.stock_bonds # Облигации
159
+ ```
160
+
161
+ ### Markets - Рыночные данные
162
+
163
+ ```ruby
164
+ # Текущие котировки
165
+ client.market_data('SBER')
166
+
167
+ # Стакан заявок
168
+ client.order_book('SBER')
169
+
170
+ # Лента сделок
171
+ client.trades('SBER')
172
+
173
+ # Итоги торговой сессии
174
+ client.trading_session
175
+ client.trading_session(date: '2024-01-15')
176
+
177
+ # Топ по объему
178
+ client.top_securities(limit: 20)
179
+
180
+ # Обороты
181
+ client.turnovers
182
+
183
+ # Эмитенты
184
+ client.issuers
185
+ client.issuer(1234)
186
+
187
+ # Открытый интерес (для фьючерсов)
188
+ client.open_interest('USDRUBF')
189
+ client.open_interest_on_date('USDRUBF', '2024-01-15')
190
+ ```
191
+
192
+ ### Автопагинация
193
+
194
+ Автоматическое получение всех страниц результатов:
195
+
196
+ ```ruby
197
+ # Способ 1: Через параметр при инициализации
198
+ client = MoexRuby::Client.new(auto_paginate: true)
199
+
200
+ # Способ 2: Через блок конфигурации
201
+ client = MoexRuby::Client.new do |config|
202
+ config.auto_paginate = true
203
+ config.timeout = 60
204
+ end
205
+
206
+ # Теперь все методы автоматически получают ВСЕ страницы
207
+ all_securities = client.securities # Получит все, а не только первые 100
208
+ all_history = client.security_history('SBER', from: '2024-01-01')
209
+
210
+ # Можно переключать динамически
211
+ client.auto_paginate = false # Выключить
212
+ result = client.securities # Вернёт только первую страницу
213
+
214
+ client.auto_paginate = true # Включить
215
+ all_results = client.securities # Вернёт все страницы
216
+ ```
217
+
218
+ ### Низкоуровневый доступ
219
+
220
+ Для специфических запросов доступен универсальный метод `get`:
221
+
222
+ ```ruby
223
+ # Прямой доступ к любому эндпоинту API
224
+ client.get('/iss/securities', q: 'Сбербанк', limit: 10)
225
+
226
+ # Ручная пагинация любого эндпоинта
227
+ client.paginate('/iss/history/...', from: '2024-01-01') do |page|
228
+ # обработка страницы
229
+ end
230
+ ```
231
+
232
+ Подробнее см. [examples/modular_api_examples.rb](./examples/modular_api_examples.rb)
233
+
9
234
  ## Документация
10
235
 
236
+ ### MOEX ISS API
11
237
  - [Руководство разработчика MOEX ISS API](https://www.moex.com/a2193)
12
238
  - [Описание методов MOEX ISS API](https://iss.moex.com/iss/reference/)
13
239
  - [Описание метаданных MOEX ISS API](https://iss.moex.com/iss/engines/stock/markets/shares/securities)
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class Client
5
+ module Engines
6
+ def engines(params = {})
7
+ get('/iss/engines', params)
8
+ end
9
+
10
+ def engine(engine, params = {})
11
+ get("/iss/engines/#{engine}", params)
12
+ end
13
+
14
+ def markets(engine, params = {})
15
+ get("/iss/engines/#{engine}/markets", params)
16
+ end
17
+
18
+ def market(engine, market, params = {})
19
+ get("/iss/engines/#{engine}/markets/#{market}", params)
20
+ end
21
+
22
+ def boards(engine, market, params = {})
23
+ get("/iss/engines/#{engine}/markets/#{market}/boards", params)
24
+ end
25
+
26
+ def board(engine, market, board, params = {})
27
+ get("/iss/engines/#{engine}/markets/#{market}/boards/#{board}", params)
28
+ end
29
+
30
+ def board_securities(engine, market, board, params = {})
31
+ get("/iss/engines/#{engine}/markets/#{market}/boards/#{board}/securities", params)
32
+ end
33
+
34
+ def board_security(engine, market, board, secid, params = {})
35
+ get("/iss/engines/#{engine}/markets/#{market}/boards/#{board}/securities/#{secid}", params)
36
+ end
37
+
38
+ def stock_shares(params = {})
39
+ board_securities('stock', 'shares', 'TQBR', params)
40
+ end
41
+
42
+ def stock_bonds(params = {})
43
+ board_securities('stock', 'bonds', 'TQCB', params)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class Client
5
+ module History
6
+ def security_history(secid, params = {})
7
+ get("/iss/history/engines/stock/markets/shares/securities/#{secid}", params)
8
+ end
9
+
10
+ def candles(secid, params = {})
11
+ get("/iss/engines/stock/markets/shares/securities/#{secid}/candles", params)
12
+ end
13
+
14
+ def bond_history(secid, params = {})
15
+ get("/iss/history/engines/stock/markets/bonds/securities/#{secid}", params)
16
+ end
17
+
18
+ def currency_history(secid, params = {})
19
+ get("/iss/history/engines/currency/markets/selt/securities/#{secid}", params)
20
+ end
21
+
22
+ def trading_days(params = {})
23
+ get('/iss/engines/stock/markets/shares/boards/TQBR/dates', params)
24
+ end
25
+
26
+ def paginate_history(secid, params = {}, &block)
27
+ path = "/iss/history/engines/stock/markets/shares/securities/#{secid}"
28
+ paginate(path, params, &block)
29
+ end
30
+
31
+ def paginate_candles(secid, params = {}, &block)
32
+ path = "/iss/engines/stock/markets/shares/securities/#{secid}/candles"
33
+ paginate(path, params, &block)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class Client
5
+ module Markets
6
+ def market_data(secid, params = {})
7
+ engine = params.delete(:engine) || 'stock'
8
+ market = params.delete(:market) || 'shares'
9
+ get("/iss/engines/#{engine}/markets/#{market}/securities/#{secid}", params)
10
+ end
11
+
12
+ def order_book(secid, params = {})
13
+ engine = params.delete(:engine) || 'stock'
14
+ market = params.delete(:market) || 'shares'
15
+ get("/iss/engines/#{engine}/markets/#{market}/orderbook/#{secid}", params)
16
+ end
17
+
18
+ def trades(secid, params = {})
19
+ engine = params.delete(:engine) || 'stock'
20
+ market = params.delete(:market) || 'shares'
21
+ get("/iss/engines/#{engine}/markets/#{market}/trades/#{secid}", params)
22
+ end
23
+
24
+ def trading_session(params = {})
25
+ engine = params.delete(:engine) || 'stock'
26
+ market = params.delete(:market) || 'shares'
27
+ get("/iss/engines/#{engine}/markets/#{market}/securities", params)
28
+ end
29
+
30
+ def top_securities(params = {})
31
+ params[:limit] ||= 20
32
+ trading_session(params)
33
+ end
34
+
35
+ def turnovers(params = {})
36
+ get('/iss/engines/stock/turnovers', params)
37
+ end
38
+
39
+ def issuers(params = {})
40
+ get('/iss/securities/issuers', params)
41
+ end
42
+
43
+ def issuer(issuer_id, params = {})
44
+ get("/iss/securities/issuers/#{issuer_id}", params)
45
+ end
46
+
47
+ def open_interest(secid, params = {})
48
+ engine = params.delete(:engine) || 'currency'
49
+ market = params.delete(:market) || 'futures'
50
+ get("/iss/engines/#{engine}/markets/#{market}/securities/#{secid}", params)
51
+ end
52
+
53
+ def open_interest_on_date(secid, date, params = {})
54
+ engine = params.delete(:engine) || 'currency'
55
+ market = params.delete(:market) || 'futures'
56
+ get("/iss/engines/#{engine}/markets/#{market}/securities/#{secid}", params.merge(date: date))
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class Client
5
+ module Securities
6
+ def security(secid, params = {})
7
+ get("/iss/securities/#{secid}", params)
8
+ end
9
+
10
+ def securities(params = {})
11
+ get('/iss/securities', params)
12
+ end
13
+
14
+ def search_securities(query, params = {})
15
+ securities(params.merge(q: query))
16
+ end
17
+
18
+ def indices(params = {})
19
+ get('/iss/statistics/engines/stock/markets/index/analytics', params)
20
+ end
21
+
22
+ def index(secid, params = {})
23
+ security(secid, params)
24
+ end
25
+
26
+ def securities_aggregates(params = {})
27
+ get('/iss/securities/aggregates', params)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+ require_relative 'connection_builder'
5
+ require_relative 'configuration'
6
+ require_relative 'response'
7
+ require_relative 'pagination_helper'
8
+ require_relative 'client/securities'
9
+ require_relative 'client/history'
10
+ require_relative 'client/engines'
11
+ require_relative 'client/markets'
12
+
13
+ module MoexRuby
14
+ class Client
15
+ extend Forwardable
16
+
17
+ include Client::Securities
18
+ include Client::History
19
+ include Client::Engines
20
+ include Client::Markets
21
+
22
+ attr_reader :connection, :config
23
+
24
+ def_delegators :@config, :auto_paginate, :auto_paginate=
25
+
26
+ def initialize(connection: nil, **config_options, &block)
27
+ @config = build_configuration(config_options, &block)
28
+ @connection = connection || build_default_connection
29
+ end
30
+
31
+ def get(path, params = {})
32
+ return perform_request(path, params) unless @config.auto_paginate
33
+
34
+ auto_paginate_get(path, params)
35
+ end
36
+
37
+ def paginate(path, params = {}, max_pages = 1000)
38
+ return enum_for(:paginate, path, params, max_pages) unless block_given?
39
+
40
+ start = 0
41
+ page = 0
42
+
43
+ loop do
44
+ page += 1
45
+
46
+ if page > max_pages
47
+ MoexRuby.logger&.warn("Pagination reached max_pages limit (#{max_pages})")
48
+ break
49
+ end
50
+
51
+ MoexRuby.logger&.debug("Fetching page #{page} with start=#{start}")
52
+ data = perform_request(path, params.merge(start: start))
53
+ size = PaginationHelper.extract_size(data)
54
+
55
+ if size.zero?
56
+ MoexRuby.logger&.debug("Empty page received, pagination complete")
57
+ break
58
+ end
59
+
60
+ yield data
61
+ start = start + size
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def perform_request(path, params)
68
+ formatted_path = ensure_json_format(path)
69
+ @connection.get(formatted_path, params)
70
+ end
71
+
72
+ def auto_paginate_get(path, params)
73
+ lazy_enumerator = Enumerator.new do |yielder|
74
+ paginate(path, params) do |page_data|
75
+ PaginationHelper.normalize_data(page_data).each do |item|
76
+ yielder << item
77
+ end
78
+ end
79
+ end
80
+
81
+ LazyResult.new(lazy_enumerator)
82
+ end
83
+
84
+ def ensure_json_format(path)
85
+ path.end_with?('.json') ? path : "#{path}.json"
86
+ end
87
+
88
+ def build_configuration(options, &block)
89
+ Configuration.new.tap do |config|
90
+ apply_options(config, options)
91
+ block&.call(config)
92
+ end
93
+ end
94
+
95
+ def apply_options(config, options)
96
+ options.each do |key, value|
97
+ next if value.nil?
98
+
99
+ setter = "#{key}="
100
+ config.public_send(setter, value) if config.respond_to?(setter)
101
+ end
102
+ end
103
+
104
+ def build_default_connection
105
+ ConnectionBuilder.new(@config).build
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class Configuration
5
+ DEFAULT_BASE_URL = 'https://iss.moex.com'
6
+ DEFAULT_TIMEOUT = 30
7
+ OPEN_TIMEOUT_RATIO = 0.33
8
+
9
+ attr_accessor :base_url, :timeout, :open_timeout, :auto_paginate
10
+ attr_reader :middleware_stack
11
+
12
+ def initialize
13
+ @base_url = DEFAULT_BASE_URL
14
+ @timeout = DEFAULT_TIMEOUT
15
+ @open_timeout = nil
16
+ @auto_paginate = false
17
+ @middleware_stack = []
18
+ @custom_block = nil
19
+ end
20
+
21
+ def request(middleware, *args, **options)
22
+ @middleware_stack << { type: :request, name: middleware, args: args, options: options }
23
+ end
24
+
25
+ def response(middleware, *args, **options)
26
+ @middleware_stack << { type: :response, name: middleware, args: args, options: options }
27
+ end
28
+
29
+ def adapter(adapter_name = nil)
30
+ @adapter = adapter_name
31
+ end
32
+
33
+ def use(middleware, *args, **options, &block)
34
+ combined_args = args
35
+ combined_args << options unless options.empty?
36
+ @middleware_stack << { type: :use, middleware: middleware, args: combined_args, block: block }
37
+ end
38
+
39
+ # Для продвинутой кастомизации через блок
40
+ def customize(&block)
41
+ @custom_block = block
42
+ end
43
+
44
+ def calculated_open_timeout
45
+ @open_timeout || (@timeout * OPEN_TIMEOUT_RATIO).ceil
46
+ end
47
+
48
+ def adapter_name
49
+ @adapter || :net_http
50
+ end
51
+
52
+ def apply_to_faraday(faraday)
53
+ # Применяем middleware из стека
54
+ @middleware_stack.each do |config|
55
+ case config[:type]
56
+ when :request
57
+ faraday.request config[:name], *config[:args], **config[:options]
58
+ when :response
59
+ faraday.response config[:name], *config[:args], **config[:options]
60
+ when :use
61
+ faraday.use config[:middleware], *config[:args], &config[:block]
62
+ end
63
+ end
64
+
65
+ # Применяем кастомный блок если есть
66
+ @custom_block&.call(faraday)
67
+ end
68
+
69
+ def has_custom_middleware?
70
+ @middleware_stack.any? || !@custom_block.nil?
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require_relative 'faraday_connection'
5
+ require_relative 'configuration'
6
+
7
+ module MoexRuby
8
+ class ConnectionBuilder
9
+ def initialize(configuration)
10
+ @config = configuration
11
+ end
12
+
13
+ def build
14
+ faraday = build_faraday_connection
15
+ FaradayConnection.new(faraday)
16
+ end
17
+
18
+ private
19
+
20
+ def build_faraday_connection
21
+ Faraday.new(url: @config.base_url) do |f|
22
+ configure_defaults(f)
23
+ apply_custom_configuration(f)
24
+ end
25
+ end
26
+
27
+ def configure_defaults(faraday)
28
+ unless @config.has_custom_middleware?
29
+ faraday.request :url_encoded
30
+ faraday.response :json, content_type: /\bjson$/
31
+ faraday.response :raise_error
32
+ end
33
+
34
+ faraday.options.timeout = @config.timeout
35
+ faraday.options.open_timeout = @config.calculated_open_timeout
36
+
37
+ faraday.adapter @config.adapter_name unless @config.has_custom_middleware?
38
+ end
39
+
40
+ def apply_custom_configuration(faraday)
41
+ @config.apply_to_faraday(faraday) if @config.has_custom_middleware?
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class DataTransformer
5
+ def initialize(columns)
6
+ @symbolized_columns = symbolize_columns(columns)
7
+ end
8
+
9
+ def transform(data)
10
+ data.map { |row| transform_row(row) }
11
+ end
12
+
13
+ private
14
+
15
+ def symbolize_columns(columns)
16
+ columns.map { |col| col.downcase.to_sym }
17
+ end
18
+
19
+ def transform_row(row)
20
+ @symbolized_columns.zip(row).to_h
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require_relative 'errors'
5
+
6
+ module MoexRuby
7
+ class ErrorHandler
8
+ ERROR_MAPPING = {
9
+ Faraday::TimeoutError => TimeoutError,
10
+ Faraday::ConnectionFailed => ConnectionError,
11
+ Faraday::ClientError => ClientError,
12
+ Faraday::ServerError => ServerError
13
+ }.freeze
14
+
15
+ def self.handle(faraday_error)
16
+ error = build_error(faraday_error)
17
+ raise error
18
+ end
19
+
20
+ def self.handled_errors
21
+ ERROR_MAPPING.keys
22
+ end
23
+
24
+ private_class_method def self.build_error(faraday_error)
25
+ error_class = find_error_class(faraday_error)
26
+
27
+ if http_error?(faraday_error)
28
+ build_http_error(error_class, faraday_error)
29
+ else
30
+ error_class.new(faraday_error.message)
31
+ end
32
+ end
33
+
34
+ private_class_method def self.find_error_class(faraday_error)
35
+ ERROR_MAPPING.each do |faraday_class, our_class|
36
+ return our_class if faraday_error.is_a?(faraday_class)
37
+ end
38
+ Error
39
+ end
40
+
41
+ private_class_method def self.http_error?(faraday_error)
42
+ faraday_error.respond_to?(:response) && faraday_error.response
43
+ end
44
+
45
+ private_class_method def self.build_http_error(error_class, faraday_error)
46
+ error_class.new(
47
+ faraday_error.message,
48
+ status: faraday_error.response[:status],
49
+ response: faraday_error.response
50
+ )
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class Error < StandardError; end
5
+
6
+ class NetworkError < Error; end
7
+ class ConnectionError < NetworkError; end
8
+ class TimeoutError < NetworkError; end
9
+
10
+ class HttpError < Error
11
+ attr_reader :status, :response
12
+
13
+ def initialize(message, status: nil, response: nil)
14
+ super(message)
15
+ @status = status
16
+ @response = response
17
+ end
18
+ end
19
+
20
+ class ClientError < HttpError; end
21
+ class ServerError < HttpError; end
22
+ class ParseError < Error; end
23
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'response'
4
+ require_relative 'error_handler'
5
+
6
+ module MoexRuby
7
+ class FaradayConnection
8
+ HANDLED_ERRORS = ErrorHandler.handled_errors.freeze
9
+
10
+ def initialize(faraday_connection)
11
+ @faraday_connection = faraday_connection
12
+ end
13
+
14
+ def get(path, params = {})
15
+ response = @faraday_connection.get(path, params)
16
+ Response.parse(response.body)
17
+ rescue *HANDLED_ERRORS => e
18
+ ErrorHandler.handle(e)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class LazyResult
5
+ include Enumerable
6
+
7
+ def initialize(enumerator)
8
+ @enumerator = enumerator
9
+ @cached_array = nil
10
+ end
11
+
12
+ def each(&block)
13
+ if block_given?
14
+ return @cached_array.each(&block) if @cached_array
15
+
16
+ @enumerator.each(&block)
17
+ else
18
+ to_enum(:each)
19
+ end
20
+ end
21
+
22
+ def to_a
23
+ @cached_array ||= @enumerator.to_a
24
+ end
25
+
26
+ def to_ary
27
+ to_a
28
+ end
29
+
30
+ def size
31
+ return @cached_array.size if @cached_array
32
+ @cached_array = @enumerator.to_a
33
+ @cached_array.size
34
+ end
35
+
36
+ def length
37
+ size
38
+ end
39
+
40
+ def empty?
41
+ return @cached_array.empty? if @cached_array
42
+
43
+ size.zero?
44
+ end
45
+
46
+ def [](index)
47
+ return @cached_array[index] if @cached_array
48
+
49
+ to_a[index]
50
+ end
51
+
52
+ def first(count = nil)
53
+ if @cached_array
54
+ return count ? @cached_array.first(count) : @cached_array.first
55
+ end
56
+
57
+ count ? to_a.first(count) : to_a.first
58
+ end
59
+
60
+ def last(count = nil)
61
+ if @cached_array
62
+ return count ? @cached_array.last(count) : @cached_array.last
63
+ end
64
+
65
+ count ? to_a.last(count) : to_a.last
66
+ end
67
+
68
+ def is_a?(klass)
69
+ super || klass == Array
70
+ end
71
+
72
+ def kind_of?(klass)
73
+ is_a?(klass)
74
+ end
75
+
76
+ def to_enum(method = :each, *args)
77
+ @enumerator.to_enum(method, *args)
78
+ end
79
+
80
+ def method_missing(name, *args, &block)
81
+ return super unless to_a.respond_to?(name)
82
+
83
+ to_a.public_send(name, *args, &block)
84
+ end
85
+
86
+ def respond_to_missing?(name, include_private = false)
87
+ to_a.respond_to?(name, include_private) || super
88
+ end
89
+
90
+ private
91
+
92
+ attr_reader :enumerator
93
+ end
94
+ end
95
+
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MoexRuby
4
+ class PaginationHelper
5
+ def self.extract_size(data)
6
+ normalize_data(data).size
7
+ end
8
+
9
+ def self.normalize_data(data)
10
+ return [] if blank?(data)
11
+
12
+ case data
13
+ when Array then data
14
+ when Hash then data.values.first || []
15
+ else []
16
+ end
17
+ end
18
+
19
+ def self.blank?(value)
20
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
21
+ end
22
+
23
+ private_class_method :blank?
24
+ end
25
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'data_transformer'
4
+
5
+ module MoexRuby
6
+ class Response
7
+ class << self
8
+ def parse(body)
9
+ return [] if blank?(body)
10
+
11
+ result = parse_blocks(body)
12
+ normalize_result(result)
13
+ end
14
+
15
+ private
16
+
17
+ def parse_blocks(body)
18
+ body.each_with_object({}) do |(block_name, block_data), result|
19
+ next unless valid_block?(block_data)
20
+
21
+ result[block_name.to_sym] = transform_block(block_data)
22
+ end
23
+ end
24
+
25
+ def valid_block?(block_data)
26
+ block_data.is_a?(Hash) &&
27
+ block_data['columns'].is_a?(Array) &&
28
+ block_data['data'].is_a?(Array)
29
+ end
30
+
31
+ def transform_block(block_data)
32
+ transformer = DataTransformer.new(block_data['columns'])
33
+ transformer.transform(block_data['data'])
34
+ end
35
+
36
+ def normalize_result(result)
37
+ result.size == 1 ? result.values.first : result
38
+ end
39
+
40
+ def blank?(value)
41
+ value.nil? || value.empty?
42
+ end
43
+ end
44
+
45
+ private_class_method :parse_blocks, :valid_block?, :transform_block, :normalize_result, :blank?
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MoexRuby
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
data/lib/moex_ruby.rb CHANGED
@@ -1,7 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'moex_ruby/version'
4
+ require_relative 'moex_ruby/errors'
5
+ require_relative 'moex_ruby/data_transformer'
6
+ require_relative 'moex_ruby/response'
7
+ require_relative 'moex_ruby/error_handler'
8
+ require_relative 'moex_ruby/configuration'
9
+ require_relative 'moex_ruby/faraday_connection'
10
+ require_relative 'moex_ruby/connection_builder'
11
+ require_relative 'moex_ruby/pagination_helper'
12
+ require_relative 'moex_ruby/lazy_result'
13
+ require_relative 'moex_ruby/client'
4
14
 
5
15
  module MoexRuby
6
- class Error < StandardError; end
16
+ class << self
17
+ attr_accessor :logger
18
+ end
19
+
20
+ def self.version
21
+ VERSION
22
+ end
7
23
  end
data/moex-ruby.gemspec CHANGED
@@ -29,8 +29,7 @@ Gem::Specification.new do |spec|
29
29
 
30
30
  spec.required_ruby_version = '>= 3.0'
31
31
 
32
- # Uncomment to register a new dependency of your gem
33
- # spec.add_runtime_dependency "example-gem", "~> 1.0"
32
+ spec.add_dependency 'faraday', '~> 2.0'
34
33
 
35
34
  # For more information and examples about making a new gem, check out our
36
35
  # guide at: https://bundler.io/guides/creating_gem.html
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moex-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pushkin Ivan
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: faraday
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.0'
12
26
  description: A Ruby gem for interacting with Moscow Exchange API to fetch market data,
13
27
  securities information, and trading statistics.
14
28
  email:
@@ -28,6 +42,20 @@ files:
28
42
  - Rakefile
29
43
  - SECURITY.md
30
44
  - lib/moex_ruby.rb
45
+ - lib/moex_ruby/client.rb
46
+ - lib/moex_ruby/client/engines.rb
47
+ - lib/moex_ruby/client/history.rb
48
+ - lib/moex_ruby/client/markets.rb
49
+ - lib/moex_ruby/client/securities.rb
50
+ - lib/moex_ruby/configuration.rb
51
+ - lib/moex_ruby/connection_builder.rb
52
+ - lib/moex_ruby/data_transformer.rb
53
+ - lib/moex_ruby/error_handler.rb
54
+ - lib/moex_ruby/errors.rb
55
+ - lib/moex_ruby/faraday_connection.rb
56
+ - lib/moex_ruby/lazy_result.rb
57
+ - lib/moex_ruby/pagination_helper.rb
58
+ - lib/moex_ruby/response.rb
31
59
  - lib/moex_ruby/version.rb
32
60
  - moex-ruby.gemspec
33
61
  homepage: https://github.com/naveroot/moex-ruby