moex_iss 1.1.0 → 1.11.1
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 +4 -4
- data/CHANGELOG.md +4 -1
- data/README.md +15 -2
- data/lib/moex_iss/client.rb +13 -1
- data/lib/moex_iss/connection.rb +0 -2
- data/lib/moex_iss/hendler.rb +6 -5
- data/lib/moex_iss/market/collection.rb +43 -0
- data/lib/moex_iss/market/currencies.rb +29 -0
- data/lib/moex_iss/market/currency.rb +14 -0
- data/lib/moex_iss/market/history/stock.rb +3 -17
- data/lib/moex_iss/market/history/stocks.rb +8 -4
- data/lib/moex_iss/market/security.rb +29 -0
- data/lib/moex_iss/market/stock.rb +7 -23
- data/lib/moex_iss/market/stocks.rb +5 -26
- data/lib/moex_iss/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc6e59c116501d2490614026723ffe37b22c554da6a7e01283e61875b2ddd2aa
|
4
|
+
data.tar.gz: 2db4b513cb7cc9dcdd12ff144c5447b23d94ea4234dc6a856de899f2ae355ff4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71eb024e491423c345d14b08a25751cbc6a535a3766773aa8d3b70ff20a68085c8402a6b8bb9058f640d262dfc6a27cb6a4254a00a405cadf1bce5a82f8a9413
|
7
|
+
data.tar.gz: 8a0b310f3682a646ee0402e19b990b7ce64c5688df504a35720214321c1ab3b126bfb629f2d4192285f4d4b9d3459d7b7136274a88b214255e29de4f97987557
|
data/CHANGELOG.md
CHANGED
@@ -4,4 +4,7 @@
|
|
4
4
|
Формат основан на ведении журнала изменений, и этот проект придерживается семантического управления версиями.
|
5
5
|
## [1.1.0] - 2023-12-30
|
6
6
|
### Добавлено
|
7
|
-
- Возможность работы с историческими данными акции
|
7
|
+
- Возможность работы с историческими данными акции
|
8
|
+
## [1.11.0] - 2024-01-03
|
9
|
+
### Добавлено
|
10
|
+
- Возможность получать данные об актуальных курсах валют ЦБ РФ
|
data/README.md
CHANGED
@@ -22,7 +22,7 @@ gem "moex_iss"
|
|
22
22
|
|
23
23
|
Или установите его самостоятельно как:
|
24
24
|
|
25
|
-
$ gem install
|
25
|
+
$ gem install moex_iss
|
26
26
|
|
27
27
|
### Поддерживаемые Ruby версии
|
28
28
|
|
@@ -37,6 +37,18 @@ gem "moex_iss"
|
|
37
37
|
client = MoexIss.client
|
38
38
|
```
|
39
39
|
|
40
|
+
### Валюты
|
41
|
+
Для получения последних актульных данных о курсах валют:
|
42
|
+
```ruby
|
43
|
+
currencies = client.currencies # => MoexIss::Market::Currencies
|
44
|
+
|
45
|
+
currencies.map(&:short_name) # -> ["USDRUB_TOM", "EURRUB_TOM", "CNYRUB_TOM"]
|
46
|
+
|
47
|
+
cny_rub = currencies.cny_rub # => MoexIss::Market::Currency
|
48
|
+
cny_rub.price = 12.5762
|
49
|
+
...
|
50
|
+
```
|
51
|
+
|
40
52
|
### Акции
|
41
53
|
|
42
54
|
Для получения последних актульных данных:
|
@@ -65,9 +77,10 @@ stocks['2023-12-03'] # => MoexIss::Market::History::Stock
|
|
65
77
|
|
66
78
|
Аргументы `from` и `till` можно использовать по одиночке
|
67
79
|
|
80
|
+
### Обратите внимание
|
68
81
|
|
69
82
|
Все экземпляры классов отвечает на метод `response`, который содержит полный ответ от MOEX ISS, из которого можно получать доп.параметры,
|
70
|
-
так же у
|
83
|
+
так же у каждого класса свой набор специфических методов для удобства работы с данными.
|
71
84
|
```ruby
|
72
85
|
# Пример
|
73
86
|
client.stock(:sber).market_price # => 271.37
|
data/lib/moex_iss/client.rb
CHANGED
@@ -6,15 +6,16 @@ module MoexIss
|
|
6
6
|
include MoexIss::Hendler
|
7
7
|
|
8
8
|
STOCKS_ENDPOINT = "engines/stock/markets/shares/boards/tqbr/securities"
|
9
|
+
CURRENCIES_ENDPOINT = "statistics/engines/currency/markets/selt/rates"
|
9
10
|
STANDARD_PARAMS = {
|
10
11
|
"iss.json" => "extended",
|
11
|
-
"iss.only" => "securities,marketdata",
|
12
12
|
"iss.meta" => "off"
|
13
13
|
}
|
14
14
|
|
15
15
|
def stocks
|
16
16
|
endpoint = "#{STOCKS_ENDPOINT}.json"
|
17
17
|
params = STANDARD_PARAMS
|
18
|
+
params["iss.only"] = "securities,marketdata"
|
18
19
|
|
19
20
|
raw_response = get(endpoint, params)
|
20
21
|
|
@@ -26,12 +27,23 @@ module MoexIss
|
|
26
27
|
|
27
28
|
endpoint = "#{STOCKS_ENDPOINT}/#{isin}.json"
|
28
29
|
params = STANDARD_PARAMS
|
30
|
+
params["iss.only"] = "securities,marketdata"
|
29
31
|
|
30
32
|
raw_response = get(endpoint, params)
|
31
33
|
|
32
34
|
MoexIss::Market::Stock.new(handle_response(raw_response))
|
33
35
|
end
|
34
36
|
|
37
|
+
def currencies
|
38
|
+
endpoint = "#{CURRENCIES_ENDPOINT}.json"
|
39
|
+
params = STANDARD_PARAMS
|
40
|
+
params["iss.only"] = "wap_rates"
|
41
|
+
|
42
|
+
raw_response = get(endpoint, params)
|
43
|
+
|
44
|
+
MoexIss::Market::Currencies.new(handle_response(raw_response))
|
45
|
+
end
|
46
|
+
|
35
47
|
private
|
36
48
|
|
37
49
|
def historical_data_of_the_stock(isin, from, till)
|
data/lib/moex_iss/connection.rb
CHANGED
data/lib/moex_iss/hendler.rb
CHANGED
@@ -4,7 +4,8 @@ module MoexIss
|
|
4
4
|
module Hendler
|
5
5
|
def handle_response(response)
|
6
6
|
return standard_hendler(response) if standard_schema?(response)
|
7
|
-
return
|
7
|
+
return response[1] if history_schema?(response)
|
8
|
+
return response[1] if currencies_schema?(response)
|
8
9
|
|
9
10
|
fail MoexIss::Error::ResponseSchemaError, "Неизвестная схема ответа"
|
10
11
|
end
|
@@ -22,14 +23,14 @@ module MoexIss
|
|
22
23
|
response.is_a?(Array) && response[1]&.has_key?("history")
|
23
24
|
end
|
24
25
|
|
26
|
+
def currencies_schema?(response)
|
27
|
+
response.is_a?(Array) && response[1]&.has_key?("wap_rates")
|
28
|
+
end
|
29
|
+
|
25
30
|
def standard_hendler(response)
|
26
31
|
response[1]["securities"].map.with_index do |x, i|
|
27
32
|
{"securities" => x, "marketdata" => response[1]["marketdata"][i]}
|
28
33
|
end
|
29
34
|
end
|
30
|
-
|
31
|
-
def history_hendler(response)
|
32
|
-
response[1]
|
33
|
-
end
|
34
35
|
end
|
35
36
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Market
|
5
|
+
class Collection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
attr_reader :response
|
9
|
+
|
10
|
+
def initialize(response, instance_class: Security)
|
11
|
+
@response = response
|
12
|
+
@instance_class = instance_class
|
13
|
+
@collection_map = {}
|
14
|
+
|
15
|
+
create_instances
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_instances
|
19
|
+
@response.each do |data|
|
20
|
+
method = method_name(data)
|
21
|
+
|
22
|
+
setup_method(method, data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def each
|
27
|
+
@collection_map.values.each { |stock| yield stock }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def method_name(data)
|
33
|
+
:some_name
|
34
|
+
end
|
35
|
+
|
36
|
+
def setup_method(method, data)
|
37
|
+
@collection_map[method] = @instance_class.new(data)
|
38
|
+
|
39
|
+
self.class.send(:define_method, method) { @collection_map[method] }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Market
|
5
|
+
class Currencies < Collection
|
6
|
+
def initialize(response, instance_class: MoexIss::Market::Currency)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_instances
|
11
|
+
@response["wap_rates"].each do |data|
|
12
|
+
method = method_name(data)
|
13
|
+
|
14
|
+
setup_method(method, data)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def method_name(data)
|
21
|
+
data["shortname"]
|
22
|
+
.split("_")
|
23
|
+
.first.downcase
|
24
|
+
.insert(3, "_")
|
25
|
+
.to_sym
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Market
|
5
|
+
class Currency < Security
|
6
|
+
METHODS = {
|
7
|
+
"tradedate" => :trade_date, "tradetime" => :trade_time,
|
8
|
+
"secid" => :secid, "shortname" => :short_name,
|
9
|
+
"price" => :price, "lasttoprevprice" => :last_top_rev_price,
|
10
|
+
"nominal" => :nominal, "decimals" => :decimals
|
11
|
+
}.freeze
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -3,31 +3,17 @@
|
|
3
3
|
module MoexIss
|
4
4
|
module Market
|
5
5
|
module History
|
6
|
-
class Stock
|
6
|
+
class Stock < Security
|
7
7
|
METHODS = {
|
8
8
|
"TRADEDATE" => :trade_date, "SHORTNAME" => :short_name, "SECID" => :secid, "VALUE" => :value,
|
9
9
|
"OPEN" => :open, "LOW" => :low, "HIGH" => :high, "LEGALCLOSEPRICE" => :legal_close_price,
|
10
10
|
"VOLUME" => :volume
|
11
11
|
}.freeze
|
12
12
|
|
13
|
-
attr_reader(:response, *METHODS.values)
|
14
|
-
|
15
13
|
def initialize(response)
|
16
|
-
|
17
|
-
|
18
|
-
setup_instance_varibales(@response["history"])
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def setup_instance_varibales(data)
|
24
|
-
return if data.nil?
|
25
|
-
|
26
|
-
data.each do |key, value|
|
27
|
-
next unless METHODS.has_key?(key)
|
14
|
+
setup_methods(response["history"])
|
28
15
|
|
29
|
-
|
30
|
-
end
|
16
|
+
super
|
31
17
|
end
|
32
18
|
end
|
33
19
|
end
|
@@ -3,15 +3,19 @@
|
|
3
3
|
module MoexIss
|
4
4
|
module Market
|
5
5
|
module History
|
6
|
-
class Stocks <
|
7
|
-
def
|
6
|
+
class Stocks < Collection
|
7
|
+
def initialize(response, instance_class: MoexIss::Market::History::Stock)
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_instances
|
8
12
|
@response["history"].each do |data|
|
9
|
-
@
|
13
|
+
@collection_map[data["TRADEDATE"]] = @instance_class.new({"history" => data})
|
10
14
|
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def [](key)
|
14
|
-
@
|
18
|
+
@collection_map[key]
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MoexIss
|
4
|
+
module Market
|
5
|
+
class Security
|
6
|
+
attr_reader :response
|
7
|
+
|
8
|
+
def initialize(response)
|
9
|
+
@response = response
|
10
|
+
|
11
|
+
setup_methods(response)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def setup_methods(data)
|
17
|
+
return if data.nil?
|
18
|
+
|
19
|
+
data.each do |key, value|
|
20
|
+
next unless self.class::METHODS.has_key?(key)
|
21
|
+
|
22
|
+
define_singleton_method self.class::METHODS[key] do
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -2,40 +2,24 @@
|
|
2
2
|
|
3
3
|
module MoexIss
|
4
4
|
module Market
|
5
|
-
class Stock
|
5
|
+
class Stock < Security
|
6
6
|
METHODS = {
|
7
7
|
"BID" => :bid, "MARKETPRICETODAY" => :market_price_today,
|
8
8
|
"MARKETPRICE" => :market_price, "SECID" => :secid,
|
9
9
|
"SHORTNAME" => :short_name, "LATNAME" => :lat_name,
|
10
10
|
"BOARDID" => :board_id, "BOARDNAME" => :board_name,
|
11
11
|
"ISIN" => :isin, "PREVPRICE" => :prev_price,
|
12
|
-
"PREVDATE" => :prev_date
|
12
|
+
"PREVDATE" => :prev_date, "CLOSEPRICE" => :close_price,
|
13
|
+
"OPEN" => :open, "LOW" => :low, "HIGH" => :high,
|
14
|
+
"LAST" => :last, "VALUE" => :value, "SYSTIME" => :systime
|
13
15
|
}.freeze
|
14
16
|
|
15
|
-
MARKET_DATA = %w[CLOSEPRICE OPEN LOW HIGH LAST VALUE SYSTIME]
|
16
|
-
|
17
|
-
attr_reader(:response, :market_data, *METHODS.values)
|
18
|
-
|
19
17
|
def initialize(response)
|
20
18
|
@response = response.is_a?(Array) ? response.first : response
|
21
19
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@market_data = @response["marketdata"]&.slice(*MARKET_DATA)
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def setup_instance_varibales(data)
|
32
|
-
return if data.nil?
|
33
|
-
|
34
|
-
data.each do |key, value|
|
35
|
-
next unless METHODS.has_key?(key)
|
36
|
-
|
37
|
-
instance_variable_set("@#{METHODS[key]}", value)
|
38
|
-
end
|
20
|
+
setup_methods(@response["securities"])
|
21
|
+
setup_methods(@response["marketdata"])
|
22
|
+
setup_methods(@response["history"])
|
39
23
|
end
|
40
24
|
end
|
41
25
|
end
|
@@ -2,36 +2,15 @@
|
|
2
2
|
|
3
3
|
module MoexIss
|
4
4
|
module Market
|
5
|
-
class Stocks
|
6
|
-
|
7
|
-
|
8
|
-
attr_reader :response
|
9
|
-
|
10
|
-
def initialize(response)
|
11
|
-
@response = response
|
12
|
-
@stocks_map = {}
|
13
|
-
|
14
|
-
create_instances_stock
|
15
|
-
end
|
16
|
-
|
17
|
-
def create_instances_stock
|
18
|
-
@response.each do |data|
|
19
|
-
method = data["securities"]["SECID"].downcase.to_sym
|
20
|
-
|
21
|
-
setup_method(method, data)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def each
|
26
|
-
@stocks_map.values.each { |stock| yield stock }
|
5
|
+
class Stocks < Collection
|
6
|
+
def initialize(response, instance_class: MoexIss::Market::Stock)
|
7
|
+
super
|
27
8
|
end
|
28
9
|
|
29
10
|
private
|
30
11
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
self.class.send(:define_method, method) { @stocks_map[method] }
|
12
|
+
def method_name(data)
|
13
|
+
data["securities"]["SECID"].downcase.to_sym
|
35
14
|
end
|
36
15
|
end
|
37
16
|
end
|
data/lib/moex_iss/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moex_iss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1
|
4
|
+
version: 1.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vyacheslav Konovalov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -96,8 +96,12 @@ files:
|
|
96
96
|
- lib/moex_iss/connection.rb
|
97
97
|
- lib/moex_iss/error.rb
|
98
98
|
- lib/moex_iss/hendler.rb
|
99
|
+
- lib/moex_iss/market/collection.rb
|
100
|
+
- lib/moex_iss/market/currencies.rb
|
101
|
+
- lib/moex_iss/market/currency.rb
|
99
102
|
- lib/moex_iss/market/history/stock.rb
|
100
103
|
- lib/moex_iss/market/history/stocks.rb
|
104
|
+
- lib/moex_iss/market/security.rb
|
101
105
|
- lib/moex_iss/market/stock.rb
|
102
106
|
- lib/moex_iss/market/stocks.rb
|
103
107
|
- lib/moex_iss/request.rb
|
@@ -126,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
130
|
- !ruby/object:Gem::Version
|
127
131
|
version: '0'
|
128
132
|
requirements: []
|
129
|
-
rubygems_version: 3.
|
133
|
+
rubygems_version: 3.1.6
|
130
134
|
signing_key:
|
131
135
|
specification_version: 4
|
132
136
|
summary: Client for MOEX ISS API
|