moex_iss 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +23 -0
- data/README.md +63 -0
- data/lib/moex_iss/client.rb +33 -0
- data/lib/moex_iss/connection.rb +42 -0
- data/lib/moex_iss/error.rb +42 -0
- data/lib/moex_iss/hendler.rb +26 -0
- data/lib/moex_iss/market/stock.rb +32 -0
- data/lib/moex_iss/market/stocks.rb +32 -0
- data/lib/moex_iss/request.rb +29 -0
- data/lib/moex_iss/version.rb +5 -0
- data/lib/moex_iss.rb +14 -0
- metadata +131 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ff742bbab0ebea3db2a2a57e0e8b76285f910ae84e27723217334ee5c86f2797
|
4
|
+
data.tar.gz: eb0ee71a6ecb99c00abc9e2eff15eaba516a9345161852250e958d92af396922
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9044394d7813c40661d5c7bf0ba690ce80972ad20d80425927d5e290aa1419ba68dcb1148592077f827aa97e16d72981948e5e0b5b5240eb27e8c89821a3a9ef
|
7
|
+
data.tar.gz: ef3537013d7b14c0b3ba6afb88a7ba25013833782ac97d56b4224cd2d459225485e1aaf74dfa944704aed6840d16d263da7b99477d683ce37b764c9d1e8b8c2a
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2023 Vyacheslav Konovalov
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/moex_iss.svg)](https://rubygems.org/gems/moex_iss)
|
2
|
+
[![Build](https://github.com/K0Hb/moex_iss/workflows/Build/badge.svg)](https://github.com/palkan/moex_iss/actions)
|
3
|
+
[![JRuby Build](https://github.com/K0Hb/moex_iss/workflows/JRuby%20Build/badge.svg)](https://github.com/K0Hb/moex_iss/actions)
|
4
|
+
|
5
|
+
# Moex Iss
|
6
|
+
|
7
|
+
Реализация части запросов к [MOEX Informational & Statistical Server](https://www.moex.com/a2193).
|
8
|
+
|
9
|
+
Реализовано несколько функций-запросов информации о торгуемых ценных бумаг, результаты которых напрямую конвертируются в Ruby класс.
|
10
|
+
|
11
|
+
Класс ценной бумаги имеет методы для получения наиболее часто использумеых показателей ценной бумаги а так же метод для получения полного ответа полученного от MOEX ISS.
|
12
|
+
|
13
|
+
## Установка
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
# Gemfile
|
17
|
+
gem "moex_iss"
|
18
|
+
```
|
19
|
+
А затем выполнить:
|
20
|
+
|
21
|
+
$ bundle install
|
22
|
+
|
23
|
+
Или установите его самостоятельно как:
|
24
|
+
|
25
|
+
$ gem install moex_api
|
26
|
+
|
27
|
+
### Поддерживаемые Ruby версии
|
28
|
+
|
29
|
+
- Ruby (MRI) >= 2.7.0
|
30
|
+
- JRuby >= 9.3.0
|
31
|
+
|
32
|
+
## Использование
|
33
|
+
|
34
|
+
### Создаем клиент
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
client = MoexIss.client
|
38
|
+
```
|
39
|
+
|
40
|
+
### Акции
|
41
|
+
|
42
|
+
Для получения одной акций:
|
43
|
+
```ruby
|
44
|
+
client.stock(:sber) # => MoexIss::Market::Stock
|
45
|
+
```
|
46
|
+
Для получения всех акций:
|
47
|
+
```ruby
|
48
|
+
client.stocks # => MoexIss::Market::Stocks
|
49
|
+
```
|
50
|
+
Получаем класс, по которому можно итерироваться а так же вызывать искомую ценную бумагу по ее `isin`
|
51
|
+
```ruby
|
52
|
+
stocks.sber
|
53
|
+
```
|
54
|
+
Экземпляр класса `MoexIss::Market::Stocks` отвечает на методы:
|
55
|
+
```ruby
|
56
|
+
%i[bid market_price_today market_price secid short_name lat_name board_id board_name isin prev_price prev_date response market_data]
|
57
|
+
```
|
58
|
+
где `response` содержит полный ответ от MOEX ISS, из которого можно получать доп.параметры
|
59
|
+
|
60
|
+
|
61
|
+
## Лицензия
|
62
|
+
|
63
|
+
Исходный код распространяется под лицензией [MIT License](http://opensource.org/licenses/MIT).
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
class Client
|
5
|
+
include MoexIss::Request
|
6
|
+
include MoexIss::Hendler
|
7
|
+
|
8
|
+
STOCKS_ENDPOINT = "engines/stock/markets/shares/boards/tqbr/securities"
|
9
|
+
STANDARD_PARAMS = {
|
10
|
+
"iss.json" => "extended",
|
11
|
+
"iss.only" => "securities,marketdata",
|
12
|
+
"iss.meta" => "off"
|
13
|
+
}
|
14
|
+
|
15
|
+
def stocks
|
16
|
+
endpoint = "#{STOCKS_ENDPOINT}.json"
|
17
|
+
params = STANDARD_PARAMS
|
18
|
+
|
19
|
+
raw_response = get(endpoint, params)
|
20
|
+
|
21
|
+
MoexIss::Market::Stocks.new(handle_response(raw_response))
|
22
|
+
end
|
23
|
+
|
24
|
+
def stock(isin)
|
25
|
+
endpoint = "#{STOCKS_ENDPOINT}/#{isin}.json"
|
26
|
+
params = STANDARD_PARAMS
|
27
|
+
|
28
|
+
raw_response = get(endpoint, params)
|
29
|
+
|
30
|
+
MoexIss::Market::Stock.new(handle_response(raw_response))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Connection
|
5
|
+
BASE_URL = "https://iss.moex.com/iss"
|
6
|
+
|
7
|
+
module DoNotEncoder
|
8
|
+
def self.encode(params)
|
9
|
+
params.map { |k, v| "#{k}=#{v}" }.join("&")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def connection
|
14
|
+
Faraday.new(options) do |con|
|
15
|
+
con.adapter Faraday.default_adapter
|
16
|
+
con.request :url_encoded
|
17
|
+
con.options.params_encoder = DoNotEncoder
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def options
|
24
|
+
headers = {
|
25
|
+
accept: "application/json",
|
26
|
+
content_type: "application/x-www-from-urlencoded",
|
27
|
+
user_agent: "moex_iss gem"
|
28
|
+
}
|
29
|
+
|
30
|
+
{
|
31
|
+
headers: headers,
|
32
|
+
url: BASE_URL
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# CURENCY https://iss.moex.com/iss/statistics/engines/currency/markets/selt/rates.json?iss.meta=off&iss.json=extended&iss.only=wap_rates
|
39
|
+
|
40
|
+
# STOCKS ALL https://iss.moex.com/iss/engines/stock/markets/shares/boards/tqbr/securities.json?iss.meta=off&iss.json=extended&iss.only=securities,marketdata&marketdata.columns=BID,OPEN,CLOSEPRICE,LOW,HIGH,LAST,VALUE,MARKETPRICETODAY,MARKETPRICE,TIME&securities.columns=SECID,SHORTNAME,LATNAME,BOARDID,BOARDNAME,ISIN,PREVPRICE
|
41
|
+
|
42
|
+
# STOCK ONE https://iss.moex.com/iss/engines/stock/markets/shares/boards/tqbr/securities/sber.json?iss.meta=off&iss.json=extended&iss.only=securities,marketdata&marketdata.columns=BID,OPEN,CLOSEPRICE,LOW,HIGH,LAST,VALUE,MARKETPRICETODAY,MARKETPRICE,TIME&securities.columns=SECID,SHORTNAME,LATNAME,BOARDID,BOARDNAME,ISIN,PREVPRICE
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
class Error < StandardError
|
5
|
+
ResponseSchemaError = Class.new(self)
|
6
|
+
ResponseParseError = Class.new(self)
|
7
|
+
|
8
|
+
ClientError = Class.new(self)
|
9
|
+
ServerError = Class.new(self)
|
10
|
+
|
11
|
+
BadRequest = Class.new(ClientError)
|
12
|
+
Unauthorized = Class.new(ClientError)
|
13
|
+
NotAcceptable = Class.new(ClientError)
|
14
|
+
NotFound = Class.new(ClientError)
|
15
|
+
Conflict = Class.new(ClientError)
|
16
|
+
TooManyRequests = Class.new(ClientError)
|
17
|
+
Forbidden = Class.new(ClientError)
|
18
|
+
Locked = Class.new(ClientError)
|
19
|
+
MethodNotAllowed = Class.new(ClientError)
|
20
|
+
|
21
|
+
NotImplemented = Class.new(ServerError)
|
22
|
+
BadGateway = Class.new(ServerError)
|
23
|
+
ServiceUnavailable = Class.new(ServerError)
|
24
|
+
GatewayTimeout = Class.new(ServerError)
|
25
|
+
|
26
|
+
ERRORS = {
|
27
|
+
400 => MoexIss::Error::BadRequest,
|
28
|
+
401 => MoexIss::Error::Unauthorized,
|
29
|
+
403 => MoexIss::Error::Forbidden,
|
30
|
+
404 => MoexIss::Error::NotFound,
|
31
|
+
405 => MoexIss::Error::MethodNotAllowed,
|
32
|
+
406 => MoexIss::Error::NotAcceptable,
|
33
|
+
409 => MoexIss::Error::Conflict,
|
34
|
+
423 => MoexIss::Error::Locked,
|
35
|
+
429 => MoexIss::Error::TooManyRequests,
|
36
|
+
500 => MoexIss::Error::ServerError,
|
37
|
+
502 => MoexIss::Error::BadGateway,
|
38
|
+
503 => MoexIss::Error::ServiceUnavailable,
|
39
|
+
504 => MoexIss::Error::GatewayTimeout
|
40
|
+
}.freeze
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Hendler
|
5
|
+
def handle_response(response)
|
6
|
+
return standard_hendler(response) if standard_schema?(response)
|
7
|
+
|
8
|
+
fail MoexIss::Error::ResponseSchemaError, "Неизвестная схема ответа"
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def standard_schema?(response)
|
14
|
+
response.is_a?(Array) &&
|
15
|
+
response[1]&.keys == %w[securities marketdata] &&
|
16
|
+
response[1]["securities"].is_a?(Array) &&
|
17
|
+
response[1]["marketdata"].is_a?(Array)
|
18
|
+
end
|
19
|
+
|
20
|
+
def standard_hendler(response)
|
21
|
+
response[1]["securities"].map.with_index do |x, i|
|
22
|
+
{"securities" => x, "marketdata" => response[1]["marketdata"][i]}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Market
|
5
|
+
class Stock
|
6
|
+
METHODS = {
|
7
|
+
"BID" => :bid, "MARKETPRICETODAY" => :market_price_today,
|
8
|
+
"MARKETPRICE" => :market_price, "SECID" => :secid,
|
9
|
+
"SHORTNAME" => :short_name, "LATNAME" => :lat_name,
|
10
|
+
"BOARDID" => :board_id, "BOARDNAME" => :board_name,
|
11
|
+
"ISIN" => :isin, "PREVPRICE" => :prev_price,
|
12
|
+
"PREVDATE" => :prev_date
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
MARKET_DATA = %w[CLOSEPRICE OPEN LOW HIGH LAST VALUE SYSTIME]
|
16
|
+
|
17
|
+
attr_reader(:response, :market_data, *METHODS.values)
|
18
|
+
|
19
|
+
def initialize(response)
|
20
|
+
@response = response.is_a?(Array) ? response.first : response
|
21
|
+
|
22
|
+
@response["securities"].merge(@response["marketdata"]).each do |key, value|
|
23
|
+
next unless METHODS.has_key?(key)
|
24
|
+
|
25
|
+
instance_variable_set("@#{METHODS[key]}", value)
|
26
|
+
end
|
27
|
+
|
28
|
+
@market_data = @response["marketdata"].slice(*MARKET_DATA)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Market
|
5
|
+
class Stocks
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :stocks_response
|
9
|
+
|
10
|
+
def initialize(stocks_response)
|
11
|
+
@stocks_response = stocks_response
|
12
|
+
@stocks_map = {}
|
13
|
+
|
14
|
+
create_instances_stock
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_instances_stock
|
18
|
+
@stocks_response.each do |stock_response|
|
19
|
+
sicid = stock_response["securities"]["SECID"].downcase.to_sym
|
20
|
+
|
21
|
+
@stocks_map[sicid] = Stock.new(stock_response)
|
22
|
+
|
23
|
+
self.class.send(:define_method, sicid) { @stocks_map[sicid] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def each
|
28
|
+
@stocks_map.values.each { |stock| yield stock }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Request
|
5
|
+
include MoexIss::Connection
|
6
|
+
|
7
|
+
def get(path, params = {})
|
8
|
+
respond_with(connection.get(path, params))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def respond_with(raw_response)
|
14
|
+
return if raw_response.body.empty?
|
15
|
+
|
16
|
+
respond_with_error(raw_response.status, raw_response.body) if !raw_response.success?
|
17
|
+
|
18
|
+
JSON.parse(raw_response.body)
|
19
|
+
rescue JSON::ParserError
|
20
|
+
raise MoexIss::Error::ResponseParseError, "Ошибка парсинга json из ответа"
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_with_error(code, body)
|
24
|
+
raise(MoexIss::Error, body) unless MoexIss::Error::ERRORS.key?(code)
|
25
|
+
|
26
|
+
raise MoexIss::Error::ERRORS[code], body
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/moex_iss.rb
ADDED
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: moex_iss
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Vyacheslav Konovalov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-12-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.9'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: faraday
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.8.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.8.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: zeitwerk
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.6.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.6.1
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- goplit2010.konovalov@yandex.ru
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files:
|
89
|
+
- README.md
|
90
|
+
files:
|
91
|
+
- CHANGELOG.md
|
92
|
+
- LICENSE.txt
|
93
|
+
- README.md
|
94
|
+
- lib/moex_iss.rb
|
95
|
+
- lib/moex_iss/client.rb
|
96
|
+
- lib/moex_iss/connection.rb
|
97
|
+
- lib/moex_iss/error.rb
|
98
|
+
- lib/moex_iss/hendler.rb
|
99
|
+
- lib/moex_iss/market/stock.rb
|
100
|
+
- lib/moex_iss/market/stocks.rb
|
101
|
+
- lib/moex_iss/request.rb
|
102
|
+
- lib/moex_iss/version.rb
|
103
|
+
homepage: https://github.com/K0Hb/moex_iss
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata:
|
107
|
+
bug_tracker_uri: https://github.com/K0Hb/moex_iss/issues
|
108
|
+
changelog_uri: https://github.com/K0Hb/moex_iss/blob/master/CHANGELOG.md
|
109
|
+
documentation_uri: https://github.com/K0Hb/moex_iss
|
110
|
+
homepage_uri: https://github.com/K0Hb/moex_iss
|
111
|
+
source_code_uri: https://github.com/K0Hb/moex_iss
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '2.7'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubygems_version: 3.5.3
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Client for MOEX ISS API
|
131
|
+
test_files: []
|